-
Andreas Ellewsen authoredAndreas Ellewsen authored
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