zips-react-native-sdk-test
Version:
Lightweight ZIPS Payment Gateway SDK for React Native - Complete payment solution with ZApp wallet payments and Access Bank integration
270 lines (269 loc) • 10.3 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, Image, } from 'react-native';
import { Button } from '../common/Button';
import { ShimmerButton } from '../common/Shimmer';
import { useWalletContext } from '../../context/WalletProvider';
import { useZipsContext } from '../../context/ZipsProvider';
export const WalletInput = () => {
const { paymentDetails, setCurrentStep } = useZipsContext();
const { selectedWallet, error, isLoading } = useWalletContext();
const [phoneNumber, setPhoneNumber] = useState('');
const [pin, setPin] = useState('');
const [phoneError, setPhoneError] = useState('');
const [pinError, setPinError] = useState('');
const validatePhoneNumber = (phone) => {
// Gambian phone number validation (7 digits)
const gambianPhoneRegex = /^[0-9]{7}$/;
return gambianPhoneRegex.test(phone);
};
const validatePin = (pinValue) => {
// PIN should be 4-6 digits
const pinRegex = /^[0-9]{4,6}$/;
return pinRegex.test(pinValue);
};
const formatPhoneNumber = (text) => {
// Remove non-digits and limit to 7 digits
const cleaned = text.replace(/\D/g, '');
return cleaned.slice(0, 7);
};
const formatPin = (text) => {
// Remove non-digits and limit to 6 digits
const cleaned = text.replace(/\D/g, '');
return cleaned.slice(0, 6);
};
const handlePhoneChange = (text) => {
const formattedPhone = formatPhoneNumber(text);
setPhoneNumber(formattedPhone);
setPhoneError('');
};
const handlePinChange = (text) => {
const formattedPin = formatPin(text);
setPin(formattedPin);
setPinError('');
};
const handleSubmit = () => {
let hasErrors = false;
// Validate phone number
if (!phoneNumber) {
setPhoneError('Phone number is required');
hasErrors = true;
}
else if (!validatePhoneNumber(phoneNumber)) {
setPhoneError('Please enter a valid 7-digit Gambian phone number');
hasErrors = true;
}
// Validate PIN for certain wallets
if (selectedWallet.id === 'afrmoney' || selectedWallet.id === 'zapp') {
if (!pin) {
setPinError('PIN is required for wallet transactions');
hasErrors = true;
}
else if (!validatePin(pin)) {
setPinError('PIN must be 4-6 digits');
hasErrors = true;
}
}
if (hasErrors) {
return;
}
const walletData = {
walletProvider: selectedWallet.id,
phoneNumber: `+220${phoneNumber}`,
pin: pin || undefined,
};
// onWalletSubmit(walletData);
};
const isFormValid = phoneNumber.length === 7 ? pin.length >= 4 : true;
const getWalletInstructions = () => {
switch (selectedWallet.id) {
case 'afrmoney':
return 'Enter your AfrMoney registered phone number and PIN to proceed with the payment.';
case 'zapp':
return 'Enter your ZApp registered phone number and PIN to complete the transaction.';
default:
return 'Enter your wallet details to proceed with the payment.';
}
};
return (_jsxs(View, { style: styles.container, children: [_jsxs(View, { style: styles.header, children: [_jsx(TouchableOpacity, { onPress: () => {
setCurrentStep('wallet-selection');
}, style: styles.backButton, children: _jsx(Text, { style: styles.backButtonText, children: "\u2190 Back" }) }), _jsx(Text, { style: styles.title, children: "Wallet Payment" }), _jsx(View, { style: styles.placeholder })] }), _jsxs(View, { style: styles.walletHeader, children: [_jsx(View, { style: styles.walletLogo, children: _jsx(Image, { source: { uri: selectedWallet.logo }, style: styles.walletLogo, resizeMode: "contain" }) }), _jsxs(View, { style: styles.walletInfo, children: [_jsx(Text, { style: styles.walletName, children: selectedWallet.name }), _jsx(Text, { style: styles.walletDescription, children: selectedWallet.description })] })] }), _jsx(Text, { style: styles.instructions, children: getWalletInstructions() }), error && (_jsx(View, { style: styles.errorContainer, children: _jsx(Text, { style: styles.errorText, children: error }) })), _jsxs(View, { style: styles.form, children: [_jsxs(View, { style: styles.formGroup, children: [_jsx(Text, { style: styles.label, children: "Phone Number *" }), _jsxs(View, { style: styles.phoneInputContainer, children: [_jsx(Text, { style: styles.countryCode, children: "+220" }), _jsx(TextInput, { style: [styles.phoneInput, phoneError ? styles.inputError : null], placeholder: "3711234", value: phoneNumber, onChangeText: handlePhoneChange, keyboardType: "numeric", maxLength: 7, editable: !isLoading, autoCorrect: false, autoCapitalize: "none", returnKeyType: "next", blurOnSubmit: false })] }), phoneError ? (_jsx(Text, { style: styles.fieldError, children: phoneError })) : null, _jsx(Text, { style: styles.helperText, children: "Enter your 7-digit Gambian phone number" })] }), _jsxs(View, { style: styles.formGroup, children: [_jsx(Text, { style: styles.label, children: "Wallet PIN *" }), _jsx(TextInput, { style: [styles.input, pinError ? styles.inputError : null], placeholder: "Enter your wallet PIN", value: pin, onChangeText: handlePinChange, keyboardType: "numeric", secureTextEntry: true, maxLength: 6, editable: !isLoading, autoCorrect: false, autoCapitalize: "none", returnKeyType: "done", blurOnSubmit: true }), pinError ? _jsx(Text, { style: styles.fieldError, children: pinError }) : null, _jsx(Text, { style: styles.helperText, children: "Enter your 4-6 digit wallet PIN" })] })] }), _jsx(View, { style: styles.submitSection, children: isLoading ? (_jsx(ShimmerButton, {})) : (_jsx(Button, { title: "Proceed to Payment", onPress: handleSubmit, disabled: !isFormValid, style: !isFormValid ? styles.submitButtonDisabled : styles.submitButton })) }), _jsx(View, { style: styles.securityNote, children: _jsx(Text, { style: styles.securityText, children: "\uD83D\uDD12 Your wallet details are encrypted and secure. We never store your PIN." }) })] }));
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff',
paddingHorizontal: 20,
paddingTop: 20,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 24,
},
backButton: {
paddingVertical: 8,
paddingHorizontal: 12,
},
backButtonText: {
fontSize: 16,
color: '#2563eb',
fontWeight: '600',
},
title: {
fontSize: 20,
fontWeight: '700',
color: '#1e293b',
textAlign: 'center',
},
placeholder: {
width: 60,
},
walletHeader: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f8fafc',
borderRadius: 12,
padding: 16,
marginBottom: 20,
borderWidth: 1,
borderColor: '#e2e8f0',
},
walletLogo: {
width: 48,
height: 48,
backgroundColor: '#ffffff',
borderRadius: 24,
alignItems: 'center',
justifyContent: 'center',
marginRight: 16,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 2,
},
logoText: {
fontSize: 24,
},
walletInfo: {
flex: 1,
},
walletName: {
fontSize: 18,
fontWeight: '600',
color: '#1e293b',
marginBottom: 4,
},
walletDescription: {
fontSize: 14,
color: '#64748b',
},
instructions: {
fontSize: 16,
color: '#475569',
lineHeight: 24,
marginBottom: 24,
textAlign: 'center',
},
errorContainer: {
backgroundColor: '#fef2f2',
borderColor: '#fecaca',
borderWidth: 1,
borderRadius: 8,
padding: 12,
marginBottom: 20,
},
errorText: {
color: '#dc2626',
fontSize: 14,
fontWeight: '500',
},
form: {
flex: 1,
},
formGroup: {
marginBottom: 24,
},
label: {
fontSize: 16,
fontWeight: '600',
color: '#374151',
marginBottom: 8,
},
phoneInputContainer: {
flexDirection: 'row',
alignItems: 'center',
borderWidth: 1,
borderColor: '#d1d5db',
borderRadius: 8,
backgroundColor: '#ffffff',
},
countryCode: {
fontSize: 16,
fontWeight: '600',
color: '#374151',
paddingLeft: 16,
paddingRight: 8,
borderRightWidth: 1,
borderRightColor: '#d1d5db',
},
phoneInput: {
flex: 1,
fontSize: 16,
paddingVertical: 12,
paddingHorizontal: 16,
color: '#374151',
},
input: {
borderWidth: 1,
borderColor: '#d1d5db',
borderRadius: 8,
fontSize: 16,
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: '#ffffff',
color: '#374151',
},
inputError: {
borderColor: '#dc2626',
backgroundColor: '#fef2f2',
},
fieldError: {
color: '#dc2626',
fontSize: 14,
marginTop: 4,
fontWeight: '500',
},
helperText: {
color: '#6b7280',
fontSize: 14,
marginTop: 4,
},
submitSection: {
paddingVertical: 20,
},
submitButton: {
backgroundColor: '#3b82f6',
borderRadius: 8,
},
submitButtonDisabled: {
backgroundColor: '#9ca3af',
opacity: 0.7,
},
securityNote: {
backgroundColor: '#f0f9ff',
borderColor: '#bae6fd',
borderWidth: 1,
borderRadius: 8,
padding: 12,
marginBottom: 20,
},
securityText: {
color: '#0369a1',
fontSize: 14,
textAlign: 'center',
fontWeight: '500',
},
});