import { useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; import { useNavigate, useParams } from 'react-router-dom'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { zodResolver } from '@hookform/resolvers/zod'; import { isNonEmptyString } from '@sniptt/guards'; import { motion } from 'framer-motion'; import { z } from 'zod'; import { Logo } from '@/auth/components/Logo'; import { Title } from '@/auth/components/Title'; import { useAuth } from '@/auth/hooks/useAuth'; import { useIsLogged } from '@/auth/hooks/useIsLogged'; import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp'; import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex'; import { AppPath } from '@/types/AppPath'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { MainButton } from '@/ui/input/button/components/MainButton'; import { TextInputV2 } from '@/ui/input/components/TextInputV2'; import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn'; import { useUpdatePasswordViaResetTokenMutation, useValidatePasswordResetTokenQuery, } from '~/generated/graphql'; import { logError } from '~/utils/logError'; const validationSchema = z .object({ passwordResetToken: z.string(), newPassword: z .string() .regex(PASSWORD_REGEX, 'Password must contain at least 8 characters'), }) .required(); type Form = z.infer; const StyledMainContainer = styled.div` display: flex; justify-content: flex-start; align-items: center; flex-direction: column; width: 100%; `; const StyledContentContainer = styled.div` margin-bottom: ${({ theme }) => theme.spacing(8)}; margin-top: ${({ theme }) => theme.spacing(4)}; width: 200px; `; const StyledForm = styled.form` align-items: center; display: flex; flex-direction: column; width: 100%; `; const StyledFullWidthMotionDiv = styled(motion.div)` width: 100%; `; const StyledInputContainer = styled.div` margin-bottom: ${({ theme }) => theme.spacing(3)}; `; export const PasswordReset = () => { const { enqueueSnackBar } = useSnackBar(); const navigate = useNavigate(); const [email, setEmail] = useState(''); const theme = useTheme(); const passwordResetToken = useParams().passwordResetToken; const isLoggedIn = useIsLogged(); const { control, handleSubmit } = useForm
({ mode: 'onChange', defaultValues: { passwordResetToken: passwordResetToken ?? '', newPassword: '', }, resolver: zodResolver(validationSchema), }); const { loading: isValidatingToken } = useValidatePasswordResetTokenQuery({ variables: { token: passwordResetToken ?? '', }, skip: !passwordResetToken, onError: (error) => { enqueueSnackBar(error?.message ?? 'Token Invalid', { variant: 'error', }); if (!isLoggedIn) { navigate(AppPath.SignInUp); } else { navigate(AppPath.Index); } }, onCompleted: (data) => { if (isNonEmptyString(data?.validatePasswordResetToken?.email)) { setEmail(data.validatePasswordResetToken.email); } }, }); const [updatePasswordViaToken, { loading: isUpdatingPassword }] = useUpdatePasswordViaResetTokenMutation(); const { signInWithCredentials } = useAuth(); const { navigateAfterSignInUp } = useNavigateAfterSignInUp(); const onSubmit = async (formData: Form) => { try { const { data } = await updatePasswordViaToken({ variables: { token: formData.passwordResetToken, newPassword: formData.newPassword, }, }); if (!data?.updatePasswordViaResetToken.success) { enqueueSnackBar('There was an error while updating password.', { variant: 'error', }); return; } if (isLoggedIn) { enqueueSnackBar('Password has been updated', { variant: 'success', }); navigate(AppPath.Index); return; } const { workspace: currentWorkspace, workspaceMember: currentWorkspaceMember, } = await signInWithCredentials(email || '', formData.newPassword); navigateAfterSignInUp(currentWorkspace, currentWorkspaceMember); } catch (err) { logError(err); enqueueSnackBar( (err as Error)?.message || 'An error occurred while updating password', { variant: 'error', }, ); } }; return ( Reset Password {isValidatingToken && ( )} {email && ( ( )} /> )} ); };