import { useEffect, useState } from 'react'; import { View, TextInput, Text, StyleSheet, TouchableOpacity, useColorScheme, ActivityIndicator, Platform, } from 'react-native'; import { debugLog } from '../../helpers/debug_log'; import { isArabicLang, getConfiguredLocalizations, } from '../../localizations/i18n'; import { StcPayService } from '../../services/stc_pay_service'; import { mapArabicNumbers } from '../../helpers/arabic_numbers_mapper'; import type { ResultCallback } from '../../models/payment_result'; import type { StcPayMoyasarStyle } from '../../models/component_models/moyasar_style'; import { readexMedium, readexRegular } from '../../helpers/fonts'; // TODO: Make this component and it's styles reusable with Stc Pay phone number component and CC export function StcPayOtp({ onPaymentResult, style: customStyle, stcPayService, }: { onPaymentResult: ResultCallback; style?: StcPayMoyasarStyle; stcPayService: StcPayService; }) { useEffect(() => { debugLog('Moyasar SDK: stc pay OTP view mounted'); return () => { debugLog('Moyasar SDK: stc pay OTP view unmounted'); }; }, []); const { t } = getConfiguredLocalizations(); const isLightMode = useColorScheme() === 'light'; const [otp, setOtp] = useState(''); const [otpError, setOtpError] = useState(null); const [isPaymentInProgress, setIsPaymentInProgress] = useState(false); const [isButtonDisabled, setIsButtonDisabled] = useState(true); useEffect(() => { setIsButtonDisabled( !!stcPayService.otpValidator.validate(otp) || isPaymentInProgress ); // stcPayService is not a changing prop // eslint-disable-next-line react-hooks/exhaustive-deps }, [otp, isPaymentInProgress]); return ( {t('moyasarTranslation:otpTitle')} { const cleanOtp = value.replace(/\s/g, '').replace(/[^\d٠-٩]/gi, ''); const mappedCleanOtp = mapArabicNumbers(cleanOtp); setOtp(mappedCleanOtp); setOtpError( stcPayService.otpValidator.visualValidate(mappedCleanOtp) ); }} placeholder={'XXXXXX'} placeholderTextColor={customStyle?.textInputsPlaceholderColor} keyboardType="numeric" editable={!isPaymentInProgress} maxLength={10} textContentType="oneTimeCode" autoComplete="sms-otp" /> {otpError} { setIsPaymentInProgress(true); await stcPayService.submitStcPaymentOtp(otp, onPaymentResult); setIsPaymentInProgress(false); }} disabled={isButtonDisabled} > {isPaymentInProgress ? ( ) : ( {t('moyasarTranslation:otpConfirm')} )} ); } const defaultStyle = StyleSheet.create({ scrollView: { maxWidth: '100%', flexGrow: 1, justifyContent: 'space-between', flexDirection: 'column', }, container: { flex: 1, padding: 25, }, title: { fontSize: 18, marginStart: 4, marginTop: 4, textAlign: 'left', direction: isArabicLang() ? 'rtl' : 'ltr', lineHeight: Platform.OS === 'ios' ? 26 : undefined, // Text gets cutoff in the custom font in AR ...readexRegular, }, inputSubContainer: { flexDirection: 'row', justifyContent: 'center', direction: isArabicLang() ? 'rtl' : 'ltr', }, buttonContainer: { flex: 1, justifyContent: 'flex-end', marginTop: 10, }, input: { width: '100%', fontSize: 18, direction: 'ltr', textAlign: isArabicLang() ? 'right' : 'left', borderWidth: 1.25, borderColor: '#DCDCDC', borderRadius: 7, marginTop: 10, marginBottom: 2, padding: 10, ...readexRegular, }, button: { minWidth: '100%', justifyContent: 'center', backgroundColor: '#480986', borderRadius: 9, padding: 10, height: 50, }, buttonText: { color: 'white', fontSize: 16, fontWeight: '500', textAlign: 'center', lineHeight: Platform.OS === 'ios' ? 26 : undefined, // Text gets cutoff in the custom font in AR ...readexMedium, }, errorText: { color: 'red', fontSize: 12, textAlign: 'left', direction: isArabicLang() ? 'rtl' : 'ltr', lineHeight: Platform.OS === 'ios' ? 26 : undefined, // Text gets cutoff in the custom font in AR ...readexRegular, }, });