2022-11-25 09:04:11 -08:00
import React from 'react' ;
2022-03-21 11:09:01 -07:00
import { defineMessages , useIntl } from 'react-intl' ;
2022-10-17 12:09:10 -07:00
import { useHistory , useParams } from 'react-router-dom' ;
2022-03-21 11:09:01 -07:00
import snackbar from 'soapbox/actions/snackbar' ;
import { confirmEmailVerification } from 'soapbox/actions/verification' ;
import { Icon , Spinner , Stack , Text } from 'soapbox/components/ui' ;
2022-10-17 12:09:10 -07:00
import { useAppDispatch , useAppSelector } from 'soapbox/hooks' ;
import { ChallengeTypes } from './index' ;
2022-03-21 11:09:01 -07:00
2022-06-09 12:08:51 -07:00
import type { AxiosError } from 'axios' ;
2022-03-21 11:09:01 -07:00
const Statuses = {
IDLE : 'IDLE' ,
SUCCESS : 'SUCCESS' ,
GENERIC_FAIL : 'GENERIC_FAIL' ,
TOKEN_NOT_FOUND : 'TOKEN_NOT_FOUND' ,
TOKEN_EXPIRED : 'TOKEN_EXPIRED' ,
} ;
const messages = defineMessages ( {
emailConfirmedHeading : { id : 'email_passthru.confirmed.heading' , defaultMessage : 'Email Confirmed!' } ,
emailConfirmedBody : { id : 'email_passthru.confirmed.body' , defaultMessage : 'Close this tab and continue the registration process on the {bold} from which you sent this email confirmation.' } ,
genericFailHeading : { id : 'email_passthru.generic_fail.heading' , defaultMessage : 'Something Went Wrong' } ,
genericFailBody : { id : 'email_passthru.generic_fail.body' , defaultMessage : 'Please request a new email confirmation.' } ,
tokenNotFoundHeading : { id : 'email_passthru.token_not_found.heading' , defaultMessage : 'Invalid Token' } ,
tokenNotFoundBody : { id : 'email_passthru.token_not_found.body' , defaultMessage : 'Your email token was not found. Please request a new email confirmation from the {bold} from which you sent this email confirmation.' } ,
tokenExpiredHeading : { id : 'email_passthru.token_expired.heading' , defaultMessage : 'Token Expired' } ,
tokenExpiredBody : { id : 'email_passthru.token_expired.body' , defaultMessage : 'Your email token has expired. Please request a new email confirmation from the {bold} from which you sent this email confirmation.' } ,
2022-11-11 15:07:02 -08:00
emailConfirmed : { id : 'email_passthru.success' , defaultMessage : 'Your email has been verified!' } ,
genericFail : { id : 'email_passthru.fail.generic' , defaultMessage : 'Unable to confirm your email' } ,
tokenExpired : { id : 'email_passthru.fail.expired' , defaultMessage : 'Your email token has expired' } ,
tokenNotFound : { id : 'email_passthru.fail.not_found' , defaultMessage : 'Your email token is invalid.' } ,
invalidToken : { id : 'email_passthru.fail.invalid_token' , defaultMessage : 'Your token is invalid' } ,
2022-03-21 11:09:01 -07:00
} ) ;
const Success = ( ) = > {
const intl = useIntl ( ) ;
2022-10-17 12:09:10 -07:00
const history = useHistory ( ) ;
const currentChallenge = useAppSelector ( ( state ) = > state . verification . currentChallenge as ChallengeTypes ) ;
// Bypass the user straight to the next step.
if ( currentChallenge === ChallengeTypes . SMS ) {
history . push ( '/verify' ) ;
return null ;
}
2022-03-21 11:09:01 -07:00
return (
< Stack space = { 4 } alignItems = 'center' >
2022-07-09 09:20:02 -07:00
< Icon src = { require ( '@tabler/icons/circle-check.svg' ) } className = 'text-primary-600 dark:text-primary-400 h-10 w-10' / >
2022-03-21 11:09:01 -07:00
< Text size = '3xl' weight = 'semibold' align = 'center' >
{ intl . formatMessage ( messages . emailConfirmedHeading ) }
< / Text >
< Text theme = 'muted' align = 'center' >
{ intl . formatMessage ( messages . emailConfirmedBody , { bold : < Text tag = 'span' weight = 'medium' > same device < / Text > } ) }
< / Text >
< / Stack >
) ;
} ;
const GenericFail = ( ) = > {
const intl = useIntl ( ) ;
return (
< Stack space = { 4 } alignItems = 'center' >
2022-07-09 09:20:02 -07:00
< Icon src = { require ( '@tabler/icons/circle-x.svg' ) } className = 'text-danger-600 h-10 w-10' / >
2022-03-21 11:09:01 -07:00
< Text size = '3xl' weight = 'semibold' align = 'center' >
{ intl . formatMessage ( messages . genericFailHeading ) }
< / Text >
< Text theme = 'muted' align = 'center' >
{ intl . formatMessage ( messages . genericFailBody ) }
< / Text >
< / Stack >
) ;
} ;
const TokenNotFound = ( ) = > {
const intl = useIntl ( ) ;
return (
< Stack space = { 4 } alignItems = 'center' >
2022-07-09 09:20:02 -07:00
< Icon src = { require ( '@tabler/icons/circle-x.svg' ) } className = 'text-danger-600 h-10 w-10' / >
2022-03-21 11:09:01 -07:00
< Text size = '3xl' weight = 'semibold' align = 'center' >
{ intl . formatMessage ( messages . tokenNotFoundHeading ) }
< / Text >
< Text theme = 'muted' align = 'center' >
{ intl . formatMessage ( messages . tokenNotFoundBody , { bold : < Text tag = 'span' weight = 'medium' > same device < / Text > } ) }
< / Text >
< / Stack >
) ;
} ;
const TokenExpired = ( ) = > {
const intl = useIntl ( ) ;
return (
< Stack space = { 4 } alignItems = 'center' >
2022-07-09 09:20:02 -07:00
< Icon src = { require ( '@tabler/icons/circle-x.svg' ) } className = 'text-danger-600 h-10 w-10' / >
2022-03-21 11:09:01 -07:00
< Text size = '3xl' weight = 'semibold' align = 'center' >
{ intl . formatMessage ( messages . tokenExpiredHeading ) }
< / Text >
< Text theme = 'muted' align = 'center' >
{ intl . formatMessage ( messages . tokenExpiredBody , { bold : < Text tag = 'span' weight = 'medium' > same device < / Text > } ) }
< / Text >
< / Stack >
) ;
} ;
2022-05-28 12:53:22 -07:00
const EmailPassThru = ( ) = > {
const { token } = useParams < { token : string } > ( ) ;
2022-03-21 11:09:01 -07:00
2022-06-20 06:46:43 -07:00
const dispatch = useAppDispatch ( ) ;
2022-03-22 05:42:26 -07:00
const intl = useIntl ( ) ;
2022-03-21 11:09:01 -07:00
const [ status , setStatus ] = React . useState ( Statuses . IDLE ) ;
React . useEffect ( ( ) = > {
if ( token ) {
dispatch ( confirmEmailVerification ( token ) )
. then ( ( ) = > {
setStatus ( Statuses . SUCCESS ) ;
2022-11-11 15:07:02 -08:00
dispatch ( snackbar . success ( intl . formatMessage ( messages . emailConfirmed ) ) ) ;
2022-03-21 11:09:01 -07:00
} )
2022-05-28 12:53:22 -07:00
. catch ( ( error : AxiosError < any > ) = > {
2022-03-21 11:09:01 -07:00
const errorKey = error ? . response ? . data ? . error ;
2022-11-11 15:07:02 -08:00
let message = intl . formatMessage ( messages . genericFail ) ;
2022-03-21 11:09:01 -07:00
if ( errorKey ) {
switch ( errorKey ) {
2022-05-11 14:06:35 -07:00
case 'token_expired' :
2022-11-11 15:07:02 -08:00
message = intl . formatMessage ( messages . tokenExpired ) ;
2022-05-11 14:06:35 -07:00
setStatus ( Statuses . TOKEN_EXPIRED ) ;
break ;
case 'token_not_found' :
2022-11-11 15:07:02 -08:00
message = intl . formatMessage ( messages . tokenNotFound ) ;
message = intl . formatMessage ( messages . invalidToken ) ;
2022-05-11 14:06:35 -07:00
setStatus ( Statuses . TOKEN_NOT_FOUND ) ;
break ;
default :
setStatus ( Statuses . GENERIC_FAIL ) ;
break ;
2022-03-21 11:09:01 -07:00
}
}
dispatch ( snackbar . error ( message ) ) ;
} ) ;
}
} , [ token ] ) ;
switch ( status ) {
2022-05-11 14:06:35 -07:00
case Statuses . SUCCESS :
return < Success / > ;
case Statuses . TOKEN_EXPIRED :
return < TokenExpired / > ;
case Statuses . TOKEN_NOT_FOUND :
return < TokenNotFound / > ;
case Statuses . GENERIC_FAIL :
return < GenericFail / > ;
default :
return < Spinner / > ;
2022-03-21 11:09:01 -07:00
}
} ;
2022-03-22 05:42:26 -07:00
export default EmailPassThru ;