优化
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
Modal,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
@@ -147,6 +148,30 @@ const WALLET_TYPE_OPTIONS = [
|
||||
},
|
||||
];
|
||||
|
||||
function getBindKeyForWallet(item: WalletItem): string | null {
|
||||
const otp = item.otpMode === true;
|
||||
switch (item.walletType) {
|
||||
case 'paytm':
|
||||
return otp ? 'paytm_personal_otp' : 'paytm_personal_token';
|
||||
case 'phonepe':
|
||||
return otp ? 'phonepe_personal_otp' : 'phonepe_personal_token';
|
||||
case 'paytm business':
|
||||
return 'paytm_business';
|
||||
case 'phonepe business':
|
||||
return 'phonepe_business';
|
||||
case 'googlepay business':
|
||||
return 'googlepay_business';
|
||||
case 'bharatpe business':
|
||||
return 'bharatpe_business';
|
||||
case 'mobikwik':
|
||||
return 'mobikwik_personal';
|
||||
case 'freecharge':
|
||||
return otp ? 'freecharge_personal' : 'freecharge_personal_token';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface HomeScreenState {
|
||||
// bind modals
|
||||
showPaytmPersonalBind: boolean;
|
||||
@@ -177,6 +202,7 @@ interface HomeScreenState {
|
||||
vpaModalSelected: string;
|
||||
// add wallet
|
||||
showAddWallet: boolean;
|
||||
bindPrefillMobile: string;
|
||||
}
|
||||
|
||||
export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
@@ -213,6 +239,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
vpaModalLoading: false,
|
||||
vpaModalSelected: '',
|
||||
showAddWallet: false,
|
||||
bindPrefillMobile: '',
|
||||
};
|
||||
this.deviceId = DeviceInfo.getUniqueIdSync();
|
||||
this.tuneUserId = Math.random().toString(36).substring(2, 15);
|
||||
@@ -330,6 +357,27 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
}
|
||||
};
|
||||
|
||||
toggleWalletActive = async (item: WalletItem, active: boolean) => {
|
||||
try {
|
||||
await Api.instance.setWalletStatus(item.id, active);
|
||||
this.setState((s) => ({
|
||||
wallets: s.wallets.map((w) =>
|
||||
w.id === item.id ? { ...w, status: active ? 'ACTIVE' : 'INACTIVE' } : w),
|
||||
}));
|
||||
} catch (e) {
|
||||
Alert.alert('Failed', (e as Error).message);
|
||||
}
|
||||
};
|
||||
|
||||
handleRebind = (item: WalletItem) => {
|
||||
const key = getBindKeyForWallet(item);
|
||||
if (!key) {
|
||||
Alert.alert('Rebind', 'Unsupported wallet type');
|
||||
return;
|
||||
}
|
||||
this.openWalletBind(key, item.phone);
|
||||
};
|
||||
|
||||
// ---- bind handlers ----
|
||||
|
||||
/** Token 等需客户端 register 的流程(与 OTP 同 modal key 时勿用推断 map) */
|
||||
@@ -360,10 +408,11 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
showPaytmPersonalBind, paytmPersonalBindType, showPhonePePersonalBind, phonePePersonalBindType,
|
||||
showPaytmBusinessBind, showPhonePeBusinessBind, showGooglePayBusinessBind, showBharatPeBusinessBind,
|
||||
showMobikwikPersonalBind, showFreechargePersonalBind, freechargePersonalBindType,
|
||||
bindPrefillMobile,
|
||||
} = this.state;
|
||||
|
||||
const close = (key: keyof HomeScreenState) => () =>
|
||||
this.setState({ [key]: false } as any);
|
||||
this.setState({ [key]: false, bindPrefillMobile: '' } as any);
|
||||
|
||||
if (showPaytmPersonalBind && paytmPersonalBindType === 'tokenMode') {
|
||||
return (
|
||||
@@ -390,6 +439,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
>
|
||||
<PayTmPersonalOTPBind
|
||||
isDebug
|
||||
initialMobile={bindPrefillMobile}
|
||||
onRequestOTP={async (wt, p) =>
|
||||
this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, {}))}
|
||||
onVerifyOTP={async (wt, p) =>
|
||||
@@ -409,6 +459,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
>
|
||||
<PhonePePersonalBind
|
||||
processString="Processing..."
|
||||
mode={1}
|
||||
userToken={Api.instance.getUserToken()}
|
||||
isDebug
|
||||
onSuccess={this.handleBindSuccess('showPhonePePersonalBind', WalletType.PHONEPE_PERSONAL, 'PhonePe Personal bound successfully') as any}
|
||||
onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePePersonalBind')(); }}
|
||||
@@ -425,6 +477,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
>
|
||||
<PhonePePersonalOTPBind
|
||||
isDebug
|
||||
initialMobile={bindPrefillMobile}
|
||||
onRequestOTP={async (wt, p) =>
|
||||
this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, {}))}
|
||||
onVerifyOTP={async (wt, p) =>
|
||||
@@ -444,6 +497,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
>
|
||||
<PaytmBusinessOTPBind
|
||||
isDebug
|
||||
initialMobile={bindPrefillMobile}
|
||||
onRequestOTP={async (wt, p) =>
|
||||
this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, {}))}
|
||||
onVerifyOTP={async (wt, p) =>
|
||||
@@ -550,6 +604,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
>
|
||||
<BharatPeBusinessOTPBind
|
||||
isDebug
|
||||
initialMobile={bindPrefillMobile}
|
||||
onRequestOTP={async (wt, p) =>
|
||||
this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile))}
|
||||
onVerifyOTP={async (wt, p) =>
|
||||
@@ -571,6 +626,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
isDebug
|
||||
deviceId={this.deviceId}
|
||||
tuneUserId={this.tuneUserId}
|
||||
initialMobile={bindPrefillMobile}
|
||||
onRequestOTP={async (wt, p) =>
|
||||
this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, { deviceId: p.deviceId, tuneUserId: p.tuneUserId }))}
|
||||
onVerifyOTP={async (wt, p) =>
|
||||
@@ -606,6 +662,7 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
>
|
||||
<FreeChargeBind
|
||||
isDebug
|
||||
initialMobile={bindPrefillMobile}
|
||||
onRequestOTP={async (wt, p) =>
|
||||
this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile))}
|
||||
onVerifyOTP={async (wt, p) =>
|
||||
@@ -619,8 +676,8 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
return null;
|
||||
};
|
||||
|
||||
openWalletBind = (key: string) => {
|
||||
this.setState({ showAddWallet: false });
|
||||
openWalletBind = (key: string, prefillMobile?: string) => {
|
||||
this.setState({ showAddWallet: false, bindPrefillMobile: prefillMobile ?? '' });
|
||||
setTimeout(() => {
|
||||
switch (key) {
|
||||
case 'paytm_personal_otp':
|
||||
@@ -779,28 +836,42 @@ export default class HomeScreen extends Component<any, HomeScreenState> {
|
||||
const color = WALLET_TYPE_COLORS[item.walletType] ?? '#888';
|
||||
const isActive = item.status === 'ACTIVE';
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={s.walletCard}
|
||||
onPress={() => this.openVpaModal(item)}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<View style={[s.walletBadge, !isActive && s.walletBadgeInactive]}>
|
||||
{WALLET_ICONS[item.walletType] ? (
|
||||
<Image source={WALLET_ICONS[item.walletType]} style={[s.walletIcon, !isActive && s.walletIconInactive]} resizeMode="contain" />
|
||||
) : (
|
||||
<View style={[s.walletIconFallback, { backgroundColor: isActive ? color : '#ccc' }]}>
|
||||
<Text style={s.walletBadgeText}>{item.walletType.split('_')[0]}</Text>
|
||||
</View>
|
||||
)}
|
||||
<View style={s.walletCard}>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.openVpaModal(item)}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<View style={[s.walletBadge, !isActive && s.walletBadgeInactive]}>
|
||||
{WALLET_ICONS[item.walletType] ? (
|
||||
<Image source={WALLET_ICONS[item.walletType]} style={[s.walletIcon, !isActive && s.walletIconInactive]} resizeMode="contain" />
|
||||
) : (
|
||||
<View style={[s.walletIconFallback, { backgroundColor: isActive ? color : '#ccc' }]}>
|
||||
<Text style={s.walletBadgeText}>{item.walletType.split('_')[0]}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={{ flex: 1, marginLeft: 12 }}>
|
||||
<Text style={s.walletPhone}>{item.phone || '—'}</Text>
|
||||
<Text style={s.walletUpi} numberOfLines={1}>{item.upi || 'No UPI'}</Text>
|
||||
</View>
|
||||
<View style={[s.statusDot, { backgroundColor: isActive ? '#2ecc71' : '#bbb' }]} />
|
||||
</View>
|
||||
<View style={{ flex: 1, marginLeft: 12 }}>
|
||||
<Text style={s.walletPhone}>{item.phone || '—'}</Text>
|
||||
<Text style={s.walletUpi} numberOfLines={1}>{item.upi || 'No UPI'}</Text>
|
||||
</View>
|
||||
<View style={[s.statusDot, { backgroundColor: isActive ? '#2ecc71' : '#bbb' }]} />
|
||||
</TouchableOpacity>
|
||||
<View style={s.walletActions}>
|
||||
{!isActive && (
|
||||
<TouchableOpacity style={s.rebindBtn} onPress={() => this.handleRebind(item)}>
|
||||
<Text style={s.rebindBtnText}>Rebind</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<Switch
|
||||
value={isActive}
|
||||
onValueChange={(v) => this.toggleWalletActive(item, v)}
|
||||
trackColor={{ false: '#ddd', true: '#2ecc7180' }}
|
||||
thumbColor={isActive ? '#2ecc71' : '#999'}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -990,6 +1061,27 @@ const s = StyleSheet.create({
|
||||
shadowRadius: 4,
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
},
|
||||
walletActions: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
marginTop: 10,
|
||||
paddingTop: 10,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderTopColor: '#eee',
|
||||
},
|
||||
rebindBtn: {
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 6,
|
||||
backgroundColor: '#3498db',
|
||||
marginRight: 12,
|
||||
},
|
||||
rebindBtnText: {
|
||||
color: '#fff',
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
},
|
||||
walletBadge: {
|
||||
width: 52,
|
||||
height: 52,
|
||||
|
||||
Reference in New Issue
Block a user