File size: 5,236 Bytes
aa2e6af | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | import { useForm } from 'react-hook-form';
import { useState, ReactNode } from 'react';
import { useOutletContext } from 'react-router-dom';
import { useRequestPasswordResetMutation } from 'librechat-data-provider/react-query';
import type { TRequestPasswordReset, TRequestPasswordResetResponse } from 'librechat-data-provider';
import type { FC } from 'react';
import type { TLoginLayoutContext } from '~/common';
import { useLocalize } from '~/hooks';
const BodyTextWrapper: FC<{ children: ReactNode }> = ({ children }) => {
return (
<div
className="relative mt-4 rounded border border-green-400 bg-green-100 px-4 py-3 text-green-700 dark:bg-green-900 dark:text-white"
role="alert"
>
{children}
</div>
);
};
const ResetPasswordBodyText = () => {
const localize = useLocalize();
return (
<div className="flex flex-col">
{localize('com_auth_reset_password_if_email_exists')}
<span>
<a className="text-sm text-green-500 hover:underline" href="/login">
{localize('com_auth_back_to_login')}
</a>
</span>
</div>
);
};
function RequestPasswordReset() {
const localize = useLocalize();
const {
register,
handleSubmit,
formState: { errors },
} = useForm<TRequestPasswordReset>();
const [bodyText, setBodyText] = useState<ReactNode | undefined>(undefined);
const { startupConfig, setHeaderText } = useOutletContext<TLoginLayoutContext>();
const requestPasswordReset = useRequestPasswordResetMutation();
const onSubmit = (data: TRequestPasswordReset) => {
requestPasswordReset.mutate(data, {
onSuccess: (data: TRequestPasswordResetResponse) => {
if (data.link && !startupConfig?.emailEnabled) {
setHeaderText('com_auth_reset_password');
setBodyText(
<span>
{localize('com_auth_click')}{' '}
<a className="text-green-500 hover:underline" href={data.link}>
{localize('com_auth_here')}
</a>{' '}
{localize('com_auth_to_reset_your_password')}
</span>,
);
} else {
setHeaderText('com_auth_reset_password_link_sent');
setBodyText(<ResetPasswordBodyText />);
}
},
onError: () => {
setHeaderText('com_auth_reset_password_link_sent');
setBodyText(<ResetPasswordBodyText />);
},
});
};
if (bodyText) {
return <BodyTextWrapper>{bodyText}</BodyTextWrapper>;
}
return (
<form
className="mt-6"
aria-label="Password reset form"
method="POST"
onSubmit={handleSubmit(onSubmit)}
>
<div className="mb-2">
<div className="relative">
<input
type="email"
id="email"
autoComplete="off"
aria-label={localize('com_auth_email')}
{...register('email', {
required: localize('com_auth_email_required'),
minLength: {
value: 3,
message: localize('com_auth_email_min_length'),
},
maxLength: {
value: 120,
message: localize('com_auth_email_max_length'),
},
pattern: {
value: /\S+@\S+\.\S+/,
message: localize('com_auth_email_pattern'),
},
})}
aria-invalid={!!errors.email}
className="webkit-dark-styles peer block w-full appearance-none rounded-md border border-gray-300 bg-transparent px-3.5 pb-3.5 pt-4 text-sm text-gray-900 focus:border-green-500 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500"
placeholder=" "
/>
<label
htmlFor="email"
className="absolute start-1 top-2 z-10 origin-[0] -translate-y-4 scale-75 transform bg-white px-3 text-sm text-gray-500 duration-100 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100 peer-focus:top-2 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-3 peer-focus:text-green-600 dark:bg-gray-900 dark:text-gray-400 dark:peer-focus:text-green-500 rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4"
>
{localize('com_auth_email_address')}
</label>
</div>
{errors.email && (
<span role="alert" className="mt-1 text-sm text-red-500 dark:text-red-900">
{errors.email.message}
</span>
)}
</div>
<div className="mt-6">
<button
type="submit"
disabled={!!errors.email}
className="w-full transform rounded-md bg-green-500 px-4 py-3 tracking-wide text-white transition-colors duration-200 hover:bg-green-550 focus:bg-green-550 focus:outline-none disabled:cursor-not-allowed disabled:hover:bg-green-500"
>
{localize('com_auth_continue')}
</button>
<div className="mt-4 flex justify-center">
<a href="/login" className="text-sm text-green-500">
{localize('com_auth_back_to_login')}
</a>
</div>
</div>
</form>
);
}
export default RequestPasswordReset;
|