import { AxiosError } from 'axios'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import OtpInput from 'react-otp-input'; import snackbar from 'soapbox/actions/snackbar'; import { confirmPhoneVerification, requestPhoneVerification } from 'soapbox/actions/verification'; import { Button, Form, FormGroup, PhoneInput, Text } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; const messages = defineMessages({ verificationInvalid: { id: 'sms_verification.invalid', defaultMessage: 'Please enter a valid phone number.' }, verificationSuccess: { id: 'sms_verification.success', defaultMessage: 'A verification code has been sent to your phone number.' }, verificationFail: { id: 'sms_verification.fail', defaultMessage: 'Failed to send SMS message to your phone number.' }, verificationExpired: { id: 'sms_verification.expired', defaultMessage: 'Your SMS token has expired.' }, phoneLabel: { id: 'sms_verification.phone.label', defaultMessage: 'Phone number' }, }); const Statuses = { IDLE: 'IDLE', REQUESTED: 'REQUESTED', FAIL: 'FAIL', }; const SmsVerification = () => { const intl = useIntl(); const dispatch = useAppDispatch(); const isLoading = useAppSelector((state) => state.verification.isLoading) as boolean; const [phone, setPhone] = React.useState(); const [status, setStatus] = React.useState(Statuses.IDLE); const [verificationCode, setVerificationCode] = React.useState(''); const [requestedAnother, setAlreadyRequestedAnother] = React.useState(false); const isValid = !!phone; const onChange = React.useCallback((phone?: string) => { setPhone(phone); }, []); const handleSubmit = React.useCallback((event) => { event.preventDefault(); if (!isValid) { setStatus(Statuses.IDLE); dispatch( snackbar.error( intl.formatMessage(messages.verificationInvalid), ), ); return; } dispatch(requestPhoneVerification(phone!)).then(() => { dispatch( snackbar.success( intl.formatMessage(messages.verificationSuccess), ), ); setStatus(Statuses.REQUESTED); }).catch((error: AxiosError) => { const message = (error.response?.data as any)?.message || intl.formatMessage(messages.verificationFail); dispatch(snackbar.error(message)); setStatus(Statuses.FAIL); }); }, [phone, isValid]); const resendVerificationCode = React.useCallback((event) => { setAlreadyRequestedAnother(true); handleSubmit(event); }, [isValid]); const submitVerification = () => { // TODO: handle proper validation from Pepe -- expired vs invalid dispatch(confirmPhoneVerification(verificationCode)) .catch(() => dispatch( snackbar.error( intl.formatMessage(messages.verificationExpired), ), )); }; React.useEffect(() => { if (verificationCode.length === 6) { submitVerification(); } }, [verificationCode]); if (status === Statuses.REQUESTED) { return (

); } return (

); }; export { SmsVerification as default };