| 
                        123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | 
                        - import Link from 'next/link'
 - import { useState } from 'react'
 - import { useTranslation } from 'react-i18next'
 - import { useRouter, useSearchParams } from 'next/navigation'
 - import { useContext } from 'use-context-selector'
 - import Button from '@/app/components/base/button'
 - import Toast from '@/app/components/base/toast'
 - import { emailRegex } from '@/config'
 - import { login } from '@/service/common'
 - import Input from '@/app/components/base/input'
 - import I18NContext from '@/context/i18n'
 - import { noop } from 'lodash-es'
 - import { resolvePostLoginRedirect } from '../utils/post-login-redirect'
 - 
 - type MailAndPasswordAuthProps = {
 -   isInvite: boolean
 -   isEmailSetup: boolean
 -   allowRegistration: boolean
 - }
 - 
 - const passwordRegex = /^(?=.*[a-zA-Z])(?=.*\d).{8,}$/
 - 
 - export default function MailAndPasswordAuth({ isInvite, isEmailSetup, allowRegistration }: MailAndPasswordAuthProps) {
 -   const { t } = useTranslation()
 -   const { locale } = useContext(I18NContext)
 -   const router = useRouter()
 -   const searchParams = useSearchParams()
 -   const [showPassword, setShowPassword] = useState(false)
 -   const emailFromLink = decodeURIComponent(searchParams.get('email') || '')
 -   const [email, setEmail] = useState(emailFromLink)
 -   const [password, setPassword] = useState('')
 - 
 -   const [isLoading, setIsLoading] = useState(false)
 -   const handleEmailPasswordLogin = async () => {
 -     if (!email) {
 -       Toast.notify({ type: 'error', message: t('login.error.emailEmpty') })
 -       return
 -     }
 -     if (!emailRegex.test(email)) {
 -       Toast.notify({
 -         type: 'error',
 -         message: t('login.error.emailInValid'),
 -       })
 -       return
 -     }
 -     if (!password?.trim()) {
 -       Toast.notify({ type: 'error', message: t('login.error.passwordEmpty') })
 -       return
 -     }
 - 
 -     try {
 -       setIsLoading(true)
 -       const loginData: Record<string, any> = {
 -         email,
 -         password,
 -         language: locale,
 -         remember_me: true,
 -       }
 -       if (isInvite)
 -         loginData.invite_token = decodeURIComponent(searchParams.get('invite_token') as string)
 -       const res = await login({
 -         url: '/login',
 -         body: loginData,
 -       })
 -       if (res.result === 'success') {
 -         if (isInvite) {
 -           router.replace(`/signin/invite-settings?${searchParams.toString()}`)
 -         }
 -         else {
 -           localStorage.setItem('console_token', res.data.access_token)
 -           localStorage.setItem('refresh_token', res.data.refresh_token)
 -           const redirectUrl = resolvePostLoginRedirect(searchParams)
 -           router.replace(redirectUrl || '/apps')
 -         }
 -       }
 -       else if (res.code === 'authentication_failed') {
 -         Toast.notify({
 -           type: 'error',
 -           message: t('login.error.invalidEmailOrPassword'),
 -         })
 -       }
 -       else {
 -         Toast.notify({
 -           type: 'error',
 -           message: res.data,
 -         })
 -       }
 -     }
 - 
 -     finally {
 -       setIsLoading(false)
 -     }
 -   }
 - 
 -   return <form onSubmit={noop}>
 -     <div className='mb-3'>
 -       <label htmlFor="email" className="system-md-semibold my-2 text-text-secondary">
 -         {t('login.email')}
 -       </label>
 -       <div className="mt-1">
 -         <Input
 -           value={email}
 -           onChange={e => setEmail(e.target.value)}
 -           disabled={isInvite}
 -           id="email"
 -           type="email"
 -           autoComplete="email"
 -           placeholder={t('login.emailPlaceholder') || ''}
 -           tabIndex={1}
 -         />
 -       </div>
 -     </div>
 - 
 -     <div className='mb-3'>
 -       <label htmlFor="password" className="my-2 flex items-center justify-between">
 -         <span className='system-md-semibold text-text-secondary'>{t('login.password')}</span>
 -         <Link
 -           href={`/reset-password?${searchParams.toString()}`}
 -           className={`system-xs-regular ${isEmailSetup ? 'text-components-button-secondary-accent-text' : 'pointer-events-none text-components-button-secondary-accent-text-disabled'}`}
 -           tabIndex={isEmailSetup ? 0 : -1}
 -           aria-disabled={!isEmailSetup}
 -         >
 -           {t('login.forget')}
 -         </Link>
 -       </label>
 -       <div className="relative mt-1">
 -         <Input
 -           id="password"
 -           value={password}
 -           onChange={e => setPassword(e.target.value)}
 -           onKeyDown={(e) => {
 -             if (e.key === 'Enter')
 -               handleEmailPasswordLogin()
 -           }}
 -           type={showPassword ? 'text' : 'password'}
 -           autoComplete="current-password"
 -           placeholder={t('login.passwordPlaceholder') || ''}
 -           tabIndex={2}
 -         />
 -         <div className="absolute inset-y-0 right-0 flex items-center">
 -           <Button
 -             type="button"
 -             variant='ghost'
 -             onClick={() => setShowPassword(!showPassword)}
 -           >
 -             {showPassword ? '👀' : '😝'}
 -           </Button>
 -         </div>
 -       </div>
 -     </div>
 - 
 -     <div className='mb-2'>
 -       <Button
 -         tabIndex={2}
 -         variant='primary'
 -         onClick={handleEmailPasswordLogin}
 -         disabled={isLoading || !email || !password}
 -         className="w-full"
 -       >{t('login.signBtn')}</Button>
 -     </div>
 -   </form>
 - }
 
 
  |