Fix form keyboard issues and sticky footers in agent screens

This commit is contained in:
Abin Toppo
2026-05-26 16:34:05 +05:30
commit 9ac5e95d52
410 changed files with 86650 additions and 0 deletions
@@ -0,0 +1,149 @@
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { ScreenShell, Input, Button, Card, AppModal } from '../../../components';
import { useAddBeneficiaryMutation } from '../services/paymentsApi';
import { useTheme } from '../../../theme';
import type { PaymentsStackParamList } from '../../../navigation/types';
import { useDispatch } from 'react-redux';
import { beneficiariesActions } from '../store/beneficiariesSlice';
type Props = NativeStackScreenProps<PaymentsStackParamList, 'AddBeneficiary'>;
export default function AddBeneficiaryScreen({ navigation }: Props) {
const theme = useTheme();
const dispatch = useDispatch();
const [addBen, { isLoading }] = useAddBeneficiaryMutation();
const [form, setForm] = useState({
name: '',
accountNumber: '',
confirmAccountNumber: '',
ifsc: '',
nickname: '',
});
const [otpModalVisible, setOtpModalVisible] = useState(false);
const [otp, setOtp] = useState('');
const isValid =
form.name.length > 2 &&
form.accountNumber.length > 6 &&
form.accountNumber === form.confirmAccountNumber &&
form.ifsc.length === 11;
const handleSubmit = () => {
if (!isValid) return;
setOtpModalVisible(true);
};
const confirmOTPAndSave = async () => {
if (otp !== '123456') return; // Mock OTP validation
setOtpModalVisible(false);
try {
const newBeneficiaryObj = {
name: form.name,
bankName: form.ifsc.startsWith('HDFC') ? 'HDFC Bank' : 'State Bank of India', // mock logic
accountMasked: form.accountNumber.slice(-4).padStart(8, 'X'),
nickname: form.nickname,
};
const payload = await addBen(newBeneficiaryObj).unwrap();
dispatch(beneficiariesActions.addBeneficiary(payload));
navigation.goBack();
} catch (e) {
console.warn("Failed to add beneficiary", e);
}
};
return (
<ScreenShell title="Add Beneficiary" subtitle="Securely save a payee for future transfers" contentContainerStyle={styles.container}>
<Card style={styles.formCard}>
<Input
label="Beneficiary Full Name"
placeholder="As per bank records"
value={form.name}
onChangeText={(v) => setForm({ ...form, name: v })}
/>
<Input
label="Account Number"
placeholder="Enter 9-18 digit account number"
secureTextEntry
keyboardType="number-pad"
value={form.accountNumber}
onChangeText={(v) => setForm({ ...form, accountNumber: v })}
/>
<Input
label="Confirm Account Number"
placeholder="Re-enter account number"
keyboardType="number-pad"
value={form.confirmAccountNumber}
onChangeText={(v) => setForm({ ...form, confirmAccountNumber: v })}
error={form.confirmAccountNumber.length > 0 && form.accountNumber !== form.confirmAccountNumber ? "Account numbers must match" : undefined}
/>
<Input
label="IFSC Code"
placeholder="e.g. SBIN0001234"
autoCapitalize="characters"
value={form.ifsc}
onChangeText={(v) => setForm({ ...form, ifsc: v })}
/>
<Input
label="Nickname (Optional)"
placeholder="e.g. Landlord, Office"
value={form.nickname}
onChangeText={(v) => setForm({ ...form, nickname: v })}
/>
</Card>
<Button
title="Verify & Save"
onPress={handleSubmit}
disabled={!isValid || isLoading}
loading={isLoading}
style={styles.submitBtn}
/>
<AppModal
visible={otpModalVisible}
onClose={() => setOtpModalVisible(false)}
title="Bank Authentication"
>
<View style={{ gap: 16 }}>
<Input
label="Enter 6-digit OTP"
placeholder="OTP sent to mobile (Hint: 123456)"
keyboardType="number-pad"
maxLength={6}
value={otp}
onChangeText={setOtp}
/>
<Button
title="Confirm Addition"
onPress={confirmOTPAndSave}
disabled={otp.length !== 6 || isLoading}
loading={isLoading}
/>
</View>
</AppModal>
</ScreenShell>
);
}
const styles = StyleSheet.create({
container: {
padding: 16,
flexGrow: 1,
},
formCard: {
padding: 16,
gap: 16,
},
submitBtn: {
marginTop: 'auto',
paddingTop: 32,
}
});