Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

ForgotPasswordForm.tsx 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. 'use client'
  2. import React, { useEffect, useState } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import { useRouter } from 'next/navigation'
  5. import { useForm } from 'react-hook-form'
  6. import { z } from 'zod'
  7. import { zodResolver } from '@hookform/resolvers/zod'
  8. import Loading from '../components/base/loading'
  9. import Input from '../components/base/input'
  10. import Button from '@/app/components/base/button'
  11. import { basePath } from '@/utils/var'
  12. import {
  13. fetchInitValidateStatus,
  14. fetchSetupStatus,
  15. sendForgotPasswordEmail,
  16. } from '@/service/common'
  17. import type { InitValidateStatusResponse } from '@/models/common'
  18. const accountFormSchema = z.object({
  19. email: z
  20. .string()
  21. .min(1, { message: 'login.error.emailInValid' })
  22. .email('login.error.emailInValid'),
  23. })
  24. type AccountFormValues = z.infer<typeof accountFormSchema>
  25. const ForgotPasswordForm = () => {
  26. const { t } = useTranslation()
  27. const router = useRouter()
  28. const [loading, setLoading] = useState(true)
  29. const [isEmailSent, setIsEmailSent] = useState(false)
  30. const { register, trigger, getValues, formState: { errors } } = useForm<AccountFormValues>({
  31. resolver: zodResolver(accountFormSchema),
  32. defaultValues: { email: '' },
  33. })
  34. const handleSendResetPasswordEmail = async (email: string) => {
  35. try {
  36. const res = await sendForgotPasswordEmail({
  37. url: '/forgot-password',
  38. body: { email },
  39. })
  40. if (res.result === 'success')
  41. setIsEmailSent(true)
  42. else console.error('Email verification failed')
  43. }
  44. catch (error) {
  45. console.error('Request failed:', error)
  46. }
  47. }
  48. const handleSendResetPasswordClick = async () => {
  49. if (isEmailSent) {
  50. router.push('/signin')
  51. }
  52. else {
  53. const isValid = await trigger('email')
  54. if (isValid) {
  55. const email = getValues('email')
  56. await handleSendResetPasswordEmail(email)
  57. }
  58. }
  59. }
  60. useEffect(() => {
  61. fetchSetupStatus().then(() => {
  62. fetchInitValidateStatus().then((res: InitValidateStatusResponse) => {
  63. if (res.status === 'not_started')
  64. window.location.href = `${basePath}/init`
  65. })
  66. setLoading(false)
  67. })
  68. }, [])
  69. return (
  70. loading
  71. ? <Loading />
  72. : <>
  73. <div className="sm:mx-auto sm:w-full sm:max-w-md">
  74. <h2 className="text-[32px] font-bold text-text-primary">
  75. {isEmailSent ? t('login.resetLinkSent') : t('login.forgotPassword')}
  76. </h2>
  77. <p className='mt-1 text-sm text-text-secondary'>
  78. {isEmailSent ? t('login.checkEmailForResetLink') : t('login.forgotPasswordDesc')}
  79. </p>
  80. </div>
  81. <div className="mt-8 grow sm:mx-auto sm:w-full sm:max-w-md">
  82. <div className="relative">
  83. <form>
  84. {!isEmailSent && (
  85. <div className='mb-5'>
  86. <label htmlFor="email"
  87. className="my-2 flex items-center justify-between text-sm font-medium text-text-primary">
  88. {t('login.email')}
  89. </label>
  90. <div className="mt-1">
  91. <Input
  92. {...register('email')}
  93. placeholder={t('login.emailPlaceholder') || ''}
  94. />
  95. {errors.email && <span className='text-sm text-red-400'>{t(`${errors.email?.message}`)}</span>}
  96. </div>
  97. </div>
  98. )}
  99. <div>
  100. <Button variant='primary' className='w-full' onClick={handleSendResetPasswordClick}>
  101. {isEmailSent ? t('login.backToSignIn') : t('login.sendResetLink')}
  102. </Button>
  103. </div>
  104. </form>
  105. </div>
  106. </div>
  107. </>
  108. )
  109. }
  110. export default ForgotPasswordForm