Fix form keyboard issues and sticky footers in agent screens
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { View, StyleSheet, Text } from 'react-native';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
import Animated, { FadeInUp } from 'react-native-reanimated';
|
||||
|
||||
import { ScreenShell, Input, Button, KeyboardAwareScrollView } from '../../../components';
|
||||
import { useTheme } from '../../../theme';
|
||||
import { TAB_BAR_HEIGHT } from '../../../utils/layoutConstants';
|
||||
import { useAppSelector } from '../../../app/hooks';
|
||||
import { selectCustomerById } from '../store/agentSelectors';
|
||||
import type { AgentCustomersStackParamList } from '../navigation/agentNavigationTypes';
|
||||
import { useCustomerForm } from '../hooks/useCustomerForm';
|
||||
|
||||
type Props = NativeStackScreenProps<AgentCustomersStackParamList, 'AddEditCustomer'>;
|
||||
|
||||
const FormSection = ({ title, icon, children }: { title: string, icon: string, children: React.ReactNode }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Animated.View entering={FadeInUp} style={[styles.section, { backgroundColor: theme.colors.surface, borderColor: theme.colors.cardBorder }]}>
|
||||
<View style={styles.sectionHeader}>
|
||||
<View style={[styles.sectionIcon, { backgroundColor: `${theme.colors.primary}15` }]}>
|
||||
<Ionicons name={icon as any} size={18} color={theme.colors.primary} />
|
||||
</View>
|
||||
<Text style={[styles.sectionTitle, { color: theme.colors.textPrimary }]}>{title}</Text>
|
||||
</View>
|
||||
<View style={styles.sectionContent}>
|
||||
{children}
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
export default function AddEditCustomerScreen({ route, navigation }: Props) {
|
||||
const { customerId } = route.params;
|
||||
const theme = useTheme();
|
||||
|
||||
const existingCustomer = useAppSelector(state =>
|
||||
customerId ? selectCustomerById(customerId)(state) : null
|
||||
);
|
||||
|
||||
const { data, errors, updateField, submit, isSubmitting } = useCustomerForm(existingCustomer || undefined);
|
||||
|
||||
const isEdit = !!existingCustomer;
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const res = await submit();
|
||||
if (res) {
|
||||
navigation.goBack();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ScreenShell title={isEdit ? 'Edit Customer' : 'Add New Customer'} scrollable={false} keyboardAware={false} withTabBar={false}>
|
||||
<View style={styles.flexContainer}>
|
||||
<KeyboardAwareScrollView contentContainerStyle={styles.scrollContent} style={styles.flex}>
|
||||
|
||||
<FormSection title="Personal Information" icon="person-outline">
|
||||
<Input
|
||||
label="Full Name"
|
||||
placeholder="e.g. Amit Sharma"
|
||||
value={data.name}
|
||||
onChangeText={(v) => updateField('name', v)}
|
||||
error={errors.name}
|
||||
/>
|
||||
<Input
|
||||
label="Phone Number"
|
||||
placeholder="10-digit number"
|
||||
value={data.phone}
|
||||
onChangeText={(v) => updateField('phone', v)}
|
||||
keyboardType="number-pad"
|
||||
maxLength={10}
|
||||
error={errors.phone}
|
||||
leftAccessory={<Text style={{ color: theme.colors.textPrimary, fontWeight: 'bold' }}>+91</Text>}
|
||||
/>
|
||||
<Input
|
||||
label="Email Address (Optional)"
|
||||
placeholder="e.g. amit@example.com"
|
||||
value={data.email}
|
||||
onChangeText={(v) => updateField('email', v)}
|
||||
keyboardType="email-address"
|
||||
autoCapitalize="none"
|
||||
error={errors.email}
|
||||
/>
|
||||
</FormSection>
|
||||
|
||||
<FormSection title="KYC Details" icon="finger-print-outline">
|
||||
<Input
|
||||
label="Aadhaar Number"
|
||||
placeholder="12-digit number"
|
||||
value={data.aadhaarNumber}
|
||||
onChangeText={(v) => updateField('aadhaarNumber', v)}
|
||||
keyboardType="number-pad"
|
||||
maxLength={12}
|
||||
error={errors.aadhaarNumber}
|
||||
/>
|
||||
<Input
|
||||
label="PAN Number"
|
||||
placeholder="e.g. ABCDE1234F"
|
||||
value={data.panNumber}
|
||||
onChangeText={(v) => updateField('panNumber', v)}
|
||||
autoCapitalize="characters"
|
||||
maxLength={10}
|
||||
error={errors.panNumber}
|
||||
/>
|
||||
</FormSection>
|
||||
|
||||
<FormSection title="Address" icon="location-outline">
|
||||
<Input
|
||||
label="Street Address"
|
||||
placeholder="House/Flat No, Area"
|
||||
value={data.address}
|
||||
onChangeText={(v) => updateField('address', v)}
|
||||
error={errors.address}
|
||||
/>
|
||||
<View style={styles.row}>
|
||||
<View style={styles.col}>
|
||||
<Input
|
||||
label="City"
|
||||
placeholder="e.g. Kolkata"
|
||||
value={data.city}
|
||||
onChangeText={(v) => updateField('city', v)}
|
||||
error={errors.city}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ width: 12 }} />
|
||||
<View style={styles.col}>
|
||||
<Input
|
||||
label="State"
|
||||
placeholder="e.g. West Bengal"
|
||||
value={data.state}
|
||||
onChangeText={(v) => updateField('state', v)}
|
||||
error={errors.state}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<Input
|
||||
label="Pincode"
|
||||
placeholder="6-digit pincode"
|
||||
value={data.pincode}
|
||||
onChangeText={(v) => updateField('pincode', v)}
|
||||
keyboardType="number-pad"
|
||||
maxLength={6}
|
||||
error={errors.pincode}
|
||||
/>
|
||||
</FormSection>
|
||||
|
||||
</KeyboardAwareScrollView>
|
||||
|
||||
<View style={[styles.footer, { backgroundColor: theme.colors.background, borderTopColor: theme.colors.cardBorder }]}>
|
||||
<Button
|
||||
title={isEdit ? 'Save Changes' : 'Add Customer'}
|
||||
onPress={handleSubmit}
|
||||
loading={isSubmitting}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ScreenShell>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
flexContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollContent: {
|
||||
padding: 16,
|
||||
paddingBottom: 24,
|
||||
},
|
||||
section: {
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
marginBottom: 24,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
sectionHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: 'rgba(0,0,0,0.05)',
|
||||
},
|
||||
sectionIcon: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 12,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 15,
|
||||
fontWeight: '700',
|
||||
},
|
||||
sectionContent: {
|
||||
padding: 16,
|
||||
paddingBottom: 16,
|
||||
gap: 16,
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
col: {
|
||||
flex: 1,
|
||||
},
|
||||
footer: {
|
||||
padding: 16,
|
||||
paddingBottom: TAB_BAR_HEIGHT + 10,
|
||||
borderTopWidth: 1,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user