import { cx, css } from '@emotion/css' import { useState } from 'react' import { useMutation } from 'react-query' import { loginWithEmail, loginWithPhone } from '@/web/api/auth' import md5 from 'md5' import toast from 'react-hot-toast' import { setCookies } from '@/web/utils/cookie' import { AnimatePresence, motion } from 'framer-motion' import { ease } from '@/web/utils/const' import { useSnapshot } from 'valtio' import uiStates from '@/web/states/uiStates' import persistedUiStates from '@/web/states/persistedUiStates' const LoginWithPhoneOrEmail = () => { const { loginPhoneCountryCode, loginType: persistedLoginType } = useSnapshot(persistedUiStates) const [email, setEmail] = useState('') const [countryCode, setCountryCode] = useState( loginPhoneCountryCode || '+86' ) const [phone, setPhone] = useState('') const [password, setPassword] = useState('') const [loginType, setLoginType] = useState<'phone' | 'email'>( persistedLoginType === 'email' ? 'email' : 'phone' ) const doEmailLogin = useMutation( () => loginWithEmail({ email: email.trim(), md5_password: md5(password.trim()), }), { onSuccess: result => { if (result?.code !== 200) { toast(`Login failed: ${result.code}`) return } setCookies(result.cookie) uiStates.showLoginPanel = false }, onError: error => { toast(`Login failed: ${error}`) }, } ) const handleEmailLogin = () => { if (!email) { toast.error('Please enter email') return } if (!password) { toast.error('Please enter password') return } if ( email.match( /^[^\s@]+@(126|163|yeah|188|vip\.163|vip\.126)\.(com|net)$/ ) == null ) { toast.error('Please use netease email') return } doEmailLogin.mutate() } const doPhoneLogin = useMutation( () => { return loginWithPhone({ countrycode: Number(countryCode.replace('+', '').trim()) || 86, phone: phone.trim(), md5_password: md5(password.trim()), }) }, { onSuccess: result => { if (result?.code !== 200) { toast(`Login failed: ${result.code}`) return } setCookies(result.cookie) uiStates.showLoginPanel = false }, onError: error => { toast(`Login failed: ${error}`) }, } ) const handlePhoneLogin = () => { if (!countryCode || !Number(countryCode.replace('+', '').trim())) { toast.error('Please enter country code') return } if (!phone) { toast.error('Please enter phone number') return } if (!password) { toast.error('Please enter password') return } doPhoneLogin.mutate() } const transition = { duration: 0.5, ease, } const variants = { hidden: { opacity: 0, transition, }, show: { opacity: 1, transition, }, } return ( <>
Log in with{' '} { const type = loginType === 'phone' ? 'email' : 'phone' setLoginType(type) persistedUiStates.loginType = type }} > Phone {' '} /{' '} { if (loginType !== 'email') setLoginType('email') }} > Email
{/* Phone input */} {loginType === 'phone' && (
{ setCountryCode(e.target.value) persistedUiStates.loginPhoneCountryCode = e.target.value }} className={cx( 'my-3.5 flex-shrink-0 bg-transparent', css` width: 28px; ` )} placeholder='+86' value={countryCode} />
setPhone(e.target.value)} className='my-3.5 flex-grow appearance-none bg-transparent' placeholder='Phone' type='tel' value={phone} />
)} {/* Email input */} {loginType === 'email' && (
setEmail(e.target.value)} className='w-full flex-grow appearance-none bg-transparent' placeholder='Email' type='email' value={email} />
)} {/* Password input */}
setPassword(e.target.value)} className='w-full bg-transparent' placeholder='Password' type='password' value={password} />
{/* Login button */}
loginType === 'phone' ? handlePhoneLogin() : handleEmailLogin() } className='mt-4 rounded-full bg-brand-700 p-4 text-center text-16 font-medium text-white' > LOG IN
) } export default LoginWithPhoneOrEmail