import React, { useCallback, useEffect, useRef, useState } from 'react'; import ConnectForm from '../components/Connect/ConnectForm'; import { withPluggy } from '../hoc/withPluggy'; import Pluggy from 'pluggy-js'; import { ErrorField, StackParams } from '../types'; import { RouteProp } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import usePollItem from '../hooks/usePollItem'; import { ConnectorCredential, ItemStatus } from 'pluggy-js/dist/types'; const CONNECTING_STATUSES = [ 'ACCOUNTS_IN_PROGRESS', 'CREDITCARDS_IN_PROGRESS', 'TRANSACTIONS_IN_PROGRESS', 'INVESTMENTS_IN_PROGRESS', 'IDENTITY_IN_PROGRESS', ]; type ConnectProps = { navigation: StackNavigationProp; route: RouteProp; pluggy: Pluggy; }; const ConnectScreen = (props: ConnectProps) => { const { navigation, route, pluggy } = props; const { institution } = route.params; const color = `#${institution.primaryColor}`; const [isLoading, setIsLoading] = useState(false); const [inputErrors, setInputErrors] = useState | undefined>(); const [errorMsg, setErrorMsg] = useState(''); const [showMfa, setShowMfa] = useState(false); const [showError, setShowError] = useState(false); const [itemId, setItemId] = useState(''); const [delay, setDelay] = useState(null); const mfaParam = useRef(null); const freshItem = usePollItem(itemId, delay); const currentCredentials = showMfa ? [mfaParam.current!] : institution.credentials!; // keep MfaParam if (freshItem && freshItem.parameter) { mfaParam.current = freshItem.parameter; } const handleSubmitForm = async (form: any) => { try { setIsLoading(true); // clean when exists itemId && pluggy.deleteItem(itemId); const itemResponse = await pluggy.createItem(Number(institution.id), form); setItemId(itemResponse.id); setDelay(1000); // start polling } catch (error) { if (error.code === 400) { setInputErrors(error.details); } else { setErrorMsg('There was an unexpected error.'); setShowError(true); } itemId && pluggy.deleteItem(itemId); setIsLoading(false); } }; const handleSubmitMfa = async (form: any) => { try { setIsLoading(true); const mfaParameter = { [mfaParam.current!.name]: form[mfaParam.current!.name] }; await pluggy.updateItemMFA(itemId, mfaParameter); setDelay(500); } catch (error) { if (error.code === 400) { setInputErrors(error.details); } else { setErrorMsg('There was an unexpected error.'); setShowError(true); } itemId && pluggy.deleteItem(itemId); setIsLoading(false); } }; const handleSubmit = showMfa ? handleSubmitMfa : handleSubmitForm; const handleClean = useCallback( name => setInputErrors(prev => prev!.filter(x => x.parameter !== name)), [], ); const handleErrorOk = useCallback(() => setShowError(false), []); useEffect(() => { if (!freshItem || freshItem.id !== itemId) { return; } switch (freshItem.status) { case ItemStatus.LOGIN_ERROR: if (delay) { setDelay(null); // stop polling setIsLoading(false); setErrorMsg('The credentials provided are invalid. Please try again'); setShowError(true); } break; case ItemStatus.UPDATING: case ItemStatus.UPDATED: if ( freshItem.executionStatus === 'SUCCESS' || CONNECTING_STATUSES.includes(freshItem.executionStatus) ) { if (delay) { setDelay(null); // stop polling setIsLoading(false); } else { // is connecting navigation.navigate('Connecting', { item: freshItem }); } } break; case ItemStatus.WAITING_USER_INPUT: if (delay && !showMfa) { setDelay(null); // stop polling setIsLoading(false); setShowMfa(true); } break; case ItemStatus.OUTDATED: { if (delay) { setDelay(null); // stop polling setIsLoading(false); if (freshItem.executionStatus === 'INVALID_CREDENTIALS_MFA') { setShowMfa(false); setErrorMsg('The extra authentication factor was not correct, try again.'); setShowError(true); } if (freshItem.executionStatus === 'ALREADY_LOGGED_IN') { setErrorMsg( 'There is an open session for that user, please close it and try again later.', ); setShowError(true); } if (freshItem.executionStatus === 'SITE_NOT_AVAILABLE') { setErrorMsg('The institution site is not available'); setShowError(true); } if (freshItem.executionStatus === 'ACCOUNT_LOCKED') { setErrorMsg( 'Your account is locked, and needs your input. Please visit the site to unlock it.', ); setShowError(true); } if (freshItem.executionStatus === 'ERROR') { setErrorMsg('There was an unexpected error.'); setShowError(true); } } break; } } }, [delay, freshItem, itemId, showMfa, navigation]); return ( ); }; ConnectScreen.displayName = 'ConnectScreen'; export default withPluggy(ConnectScreen);