import * as React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; import snackbar from 'soapbox/actions/snackbar'; import { confirmEmailVerification } from 'soapbox/actions/verification'; import { Icon, Spinner, Stack, Text } from 'soapbox/components/ui'; import type { AxiosError } from 'axios'; 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.' }, }); const Success = () => { const intl = useIntl(); return ( {intl.formatMessage(messages.emailConfirmedHeading)} {intl.formatMessage(messages.emailConfirmedBody, { bold: same device })} ); }; const GenericFail = () => { const intl = useIntl(); return ( {intl.formatMessage(messages.genericFailHeading)} {intl.formatMessage(messages.genericFailBody)} ); }; const TokenNotFound = () => { const intl = useIntl(); return ( {intl.formatMessage(messages.tokenNotFoundHeading)} {intl.formatMessage(messages.tokenNotFoundBody, { bold: same device })} ); }; const TokenExpired = () => { const intl = useIntl(); return ( {intl.formatMessage(messages.tokenExpiredHeading)} {intl.formatMessage(messages.tokenExpiredBody, { bold: same device })} ); }; const EmailPassThru = () => { const { token } = useParams<{ token: string }>(); const dispatch = useDispatch(); const intl = useIntl(); const [status, setStatus] = React.useState(Statuses.IDLE); React.useEffect(() => { if (token) { dispatch(confirmEmailVerification(token)) .then(() => { setStatus(Statuses.SUCCESS); dispatch(snackbar.success(intl.formatMessage({ id: 'email_passthru.success', defaultMessage: 'Your email has been verified!' }))); }) .catch((error: AxiosError) => { const errorKey = error?.response?.data?.error; let message = intl.formatMessage({ id: 'email_passthru.fail.generic', defaultMessage: 'Unable to confirm your email', }); if (errorKey) { switch (errorKey) { case 'token_expired': message = intl.formatMessage({ id: 'email_passthru.fail.expired', defaultMessage: 'Your email token has expired.', }); setStatus(Statuses.TOKEN_EXPIRED); break; case 'token_not_found': message = intl.formatMessage({ id: 'email_passthru.fail.not_found', defaultMessage: 'Your email token is invalid.', }); message = 'Your token is invalid'; setStatus(Statuses.TOKEN_NOT_FOUND); break; default: setStatus(Statuses.GENERIC_FAIL); break; } } dispatch(snackbar.error(message)); }); } }, [token]); switch (status) { case Statuses.SUCCESS: return ; case Statuses.TOKEN_EXPIRED: return ; case Statuses.TOKEN_NOT_FOUND: return ; case Statuses.GENERIC_FAIL: return ; default: return ; } }; export default EmailPassThru;