import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import Page from 'components/page' import Loading from 'components/loading' import { useUserContext } from 'contexts' import { setCookie, submitJsonOpts } from 'utils' import LoginBox from 'components/loginBox' import { Container, Typography } from '@mui/material' function ChooseRegistrationMethod() { const { t } = useTranslation(['invite']) // If the user clicks on login using Feide we want him to be sent to the // guest register page afterwards const setCookieLogin = () => { setCookie('redirect', '/guestregister') } return ( <Page> <Container maxWidth="md" sx={{ display: 'flex', flexDirection: 'column', marginTop: '2rem', marginBottom: '8rem', }} > <Typography variant="h1" sx={{ marginBottom: '2rem' }}> {t('header')} </Typography> <Typography variant="body1" sx={{ marginBottom: '2rem' }}> {t('description')} </Typography> <LoginBox header={t('guest')} info={t('guestInfo')} manual large onClickLogin={setCookieLogin} /> </Container> </Page> ) } interface ShowFeedbackProps { title: string description: string } function ShowFeedback(props: ShowFeedbackProps) { const { title, description } = props return ( <Page> <Typography variant="h1">{title}</Typography> <Typography variant="body1">{description}</Typography> </Page> ) } function Invite() { const { t } = useTranslation(['invite']) const { user, fetchUserInfo } = useUserContext() const [inviteToken, setInviteToken] = useState('') const [tokenChecked, setTokenChecked] = useState(false) const [isCheckingToken, setIsCheckingToken] = useState(false) const [tokenOk, setTokenOk] = useState(false) const [checkError, setCheckError] = useState('') async function checkToken(token: string) { try { const response = await fetch( '/api/ui/v1/invitecheck/', submitJsonOpts('POST', { invite_token: token }) ) if (response.status === 200) { setTokenOk(true) return } const data = await response.json() if ('code' in data) { setCheckError(data.code) } else { setCheckError('unknown') } } catch (error) { console.error(error) setCheckError('unknown') } finally { setTokenChecked(true) setIsCheckingToken(false) } } console.log({ inviteToken, isCheckingToken, tokenChecked, tokenOk, user }) useEffect(() => { setIsCheckingToken(true) // This may seem unecessary, but race conditions have been // observed where the userinfo endpoint is called too fast // and no invite_id is found in the server-side session setTimeout(fetchUserInfo, 100) }, [setTokenOk]) if (user.auth) { return <ChooseRegistrationMethod /> } if (isCheckingToken || (tokenOk && !user.auth)) { return <Loading /> } if (inviteToken !== '' && !tokenChecked) { checkToken(inviteToken) return <Loading /> } if (checkError !== '') { if ( checkError === 'missing_invite_token' || checkError === 'invalid_invite_token' ) { // Missing or invalid token return ( <ShowFeedback title={t('common:error.error')} description={t('invite:errors.invalidToken')} /> ) } if (checkError === 'expired_invite_token') { // Expired token return ( <ShowFeedback title={t('common:error.error')} description={t('invite:errors.expiredToken')} /> ) } // Unknown error return ( <ShowFeedback title={t('common:error.error')} description={t('common:error.unknown')} /> ) } const providedToken = window.location.hash.slice(1).trim() if (!inviteToken && providedToken) { setInviteToken(providedToken) return <Loading /> } // We'll end up here if no token was provided in the URL return ( <ShowFeedback title={t('common:error.error')} description={t('invite:errors.invalidToken')} /> ) } export default Invite