mail-and-code-auth.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { useState } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { useRouter, useSearchParams } from 'next/navigation'
  4. import { useContext } from 'use-context-selector'
  5. import Input from '@/app/components/base/input'
  6. import Button from '@/app/components/base/button'
  7. import { emailRegex } from '@/config'
  8. import Toast from '@/app/components/base/toast'
  9. import { sendEMailLoginCode } from '@/service/common'
  10. import { COUNT_DOWN_KEY, COUNT_DOWN_TIME_MS } from '@/app/components/signin/countdown'
  11. import I18NContext from '@/context/i18n'
  12. type MailAndCodeAuthProps = {
  13. isInvite: boolean
  14. }
  15. export default function MailAndCodeAuth({ isInvite }: MailAndCodeAuthProps) {
  16. const { t } = useTranslation()
  17. const router = useRouter()
  18. const searchParams = useSearchParams()
  19. const emailFromLink = decodeURIComponent(searchParams.get('email') || '')
  20. const [email, setEmail] = useState(emailFromLink)
  21. const [loading, setIsLoading] = useState(false)
  22. const { locale } = useContext(I18NContext)
  23. const handleGetEMailVerificationCode = async () => {
  24. try {
  25. if (!email) {
  26. Toast.notify({ type: 'error', message: t('login.error.emailEmpty') })
  27. return
  28. }
  29. if (!emailRegex.test(email)) {
  30. Toast.notify({
  31. type: 'error',
  32. message: t('login.error.emailInValid'),
  33. })
  34. return
  35. }
  36. setIsLoading(true)
  37. const ret = await sendEMailLoginCode(email, locale)
  38. if (ret.result === 'success') {
  39. localStorage.setItem(COUNT_DOWN_KEY, `${COUNT_DOWN_TIME_MS}`)
  40. const params = new URLSearchParams(searchParams)
  41. params.set('email', encodeURIComponent(email))
  42. params.set('token', encodeURIComponent(ret.data))
  43. router.push(`/signin/check-code?${params.toString()}`)
  44. }
  45. }
  46. catch (error) {
  47. console.error(error)
  48. }
  49. finally {
  50. setIsLoading(false)
  51. }
  52. }
  53. return (<form onSubmit={() => { }}>
  54. <input type='text' className='hidden' />
  55. <div className='mb-2'>
  56. <label htmlFor="email" className='my-2 system-md-semibold text-text-secondary'>{t('login.email')}</label>
  57. <div className='mt-1'>
  58. <Input id='email' type="email" disabled={isInvite} value={email} placeholder={t('login.emailPlaceholder') as string} onChange={e => setEmail(e.target.value)} />
  59. </div>
  60. <div className='mt-3'>
  61. <Button loading={loading} disabled={loading || !email} variant='primary' className='w-full' onClick={handleGetEMailVerificationCode}>{t('login.continueWithCode')}</Button>
  62. </div>
  63. </div>
  64. </form>
  65. )
  66. }