import clsx from 'clsx'; import { h, Fragment } from 'preact'; import { useState } from 'preact/hooks'; import { useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { setUser } from 'store/user/actions'; import { Input } from 'components/input'; import { CrossIcon } from 'components/icons/cross'; import { TextareaAutosize } from 'components/textarea-autosize'; import { Spinner } from 'components/spinner/spinner'; import { ArrowIcon } from 'components/icons/arrow'; import { Button } from './components/button'; import { OAuth } from './components/oauth'; import { messages } from './auth.messsages'; import { useDropdown } from './auth.hooks'; import { getProviders, getTokenInvalidReason } from './auth.utils'; import { emailSignin, verifyEmailSignin, anonymousSignin } from './auth.api'; import styles from './auth.module.css'; export function Auth() { const intl = useIntl(); const dispath = useDispatch(); const [oauthProviders, formProviders] = getProviders(); // UI State const [isLoading, setLoading] = useState(false); const [view, setView] = useState(formProviders[0]); const [ref, isDropdownShowed, toggleDropdownState] = useDropdown(view === 'token'); // Errors const [invalidReason, setInvalidReason] = useState(null); function handleClickSingIn(evt: Event) { evt.preventDefault(); toggleDropdownState(); } function handleDropdownClose(evt: Event) { evt.preventDefault(); setView(formProviders[0]); toggleDropdownState(); } function handleProviderChange(evt: Event) { const { value } = evt.currentTarget as HTMLInputElement; setInvalidReason(null); setView(value as typeof formProviders[number]); } async function handleSubmit(evt: Event) { const data = new FormData(evt.target as HTMLFormElement); evt.preventDefault(); setLoading(true); setInvalidReason(null); try { switch (view) { case 'anonymous': { const username = data.get('username') as string; const user = await anonymousSignin(username); dispath(setUser(user)); break; } case 'email': { const email = data.get('email') as string; const username = data.get('username') as string; await emailSignin(email, username); setView('token'); break; } case 'token': { const token = data.get('token') as string; const invalidReason = getTokenInvalidReason(token); if (invalidReason) { setInvalidReason(invalidReason); } else { const user = await verifyEmailSignin(token); dispath(setUser(user)); } break; } } } catch (e) { setInvalidReason(e.message || e.error); } setLoading(false); } function handleShowEmailStep(evt: Event) { evt.preventDefault(); setView('email'); } const hasOAuthProviders = oauthProviders.length > 0; const hasFormProviders = formProviders.length > 0; const errorMessage = invalidReason !== null && messages[invalidReason] ? intl.formatMessage(messages[invalidReason]) : invalidReason; const isTokenView = view === 'token'; const formFooterJSX = ( <> {errorMessage &&
{errorMessage}
} ); return (
{isDropdownShowed && (
{isTokenView ? ( <>
{formFooterJSX} ) : ( <> {hasOAuthProviders && ( <>
{intl.formatMessage(messages.oauthSource)}
)} {hasOAuthProviders && hasFormProviders && (
)} {hasFormProviders && ( <> {formProviders.length === 1 ? (
{formProviders[0]}
) : (
{formProviders.map((p) => ( ))}
)}
{ const element = evt.target as HTMLInputElement; element.value = element.value.trim(); }} />
{view === 'email' && (
)} {formFooterJSX} )} )}
)}
); }