Fix form keyboard issues and sticky footers in agent screens
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
import React from 'react';
|
||||
import { View, Text, StyleSheet, ScrollView, Pressable, Alert } from 'react-native';
|
||||
import { CompositeNavigationProp } from '@react-navigation/native';
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
|
||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
import Animated, { FadeInUp } from 'react-native-reanimated';
|
||||
|
||||
import { ScreenShell, Button } from '../../../components';
|
||||
import { useTheme } from '../../../theme';
|
||||
import { TAB_BAR_HEIGHT } from '../../../utils/layoutConstants';
|
||||
import { useAppDispatch, useAppSelector } from '../../../app/hooks';
|
||||
import type { AgentTabParamList, AgentProfileStackParamList } from '../navigation/agentNavigationTypes';
|
||||
import { logoutSession } from '../../auth/store/authThunk';
|
||||
|
||||
type NavigationProp = CompositeNavigationProp<
|
||||
NativeStackNavigationProp<AgentProfileStackParamList, 'AgentProfileMain'>,
|
||||
BottomTabNavigationProp<AgentTabParamList>
|
||||
>;
|
||||
|
||||
export default function AgentProfileScreen({ navigation }: { navigation: NavigationProp }) {
|
||||
const theme = useTheme();
|
||||
const dispatch = useAppDispatch();
|
||||
const profile = useAppSelector(state => state.user.profile);
|
||||
|
||||
const handleLogout = () => {
|
||||
Alert.alert(
|
||||
'Log Out',
|
||||
'Are you sure you want to log out of your agent account?',
|
||||
[
|
||||
{ text: 'Cancel', style: 'cancel' },
|
||||
{
|
||||
text: 'Log Out',
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
dispatch(logoutSession());
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
const SettingsRow = ({ icon, label, onPress, destructive = false }: { icon: string, label: string, onPress: () => void, destructive?: boolean }) => (
|
||||
<Pressable
|
||||
style={styles.settingsRow}
|
||||
onPress={onPress}
|
||||
>
|
||||
<View style={styles.settingsRowLeft}>
|
||||
<View style={[styles.settingsIconFrame, { backgroundColor: destructive ? `${theme.colors.danger}15` : `${theme.colors.primary}15` }]}>
|
||||
<Ionicons name={icon as any} size={20} color={destructive ? theme.colors.danger : theme.colors.primary} />
|
||||
</View>
|
||||
<Text style={[styles.settingsLabel, { color: destructive ? theme.colors.danger : theme.colors.textPrimary }]}>{label}</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward" size={20} color={theme.colors.textMuted} />
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
return (
|
||||
<ScreenShell title="Agent Profile" scrollable={false}>
|
||||
<ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
||||
|
||||
<Animated.View entering={FadeInUp} style={[styles.profileCard, { backgroundColor: theme.colors.surface, borderColor: theme.colors.cardBorder }]}>
|
||||
<View style={[styles.avatarBig, { backgroundColor: `${theme.colors.primary}15` }]}>
|
||||
<Text style={[styles.avatarText, { color: theme.colors.primary }]}>{profile?.firstName?.charAt(0) || 'A'}</Text>
|
||||
</View>
|
||||
<Text style={[styles.name, { color: theme.colors.textPrimary }]}>{profile?.firstName} {profile?.lastName}</Text>
|
||||
<Text style={[styles.role, { color: theme.colors.textMuted }]}>Field Agent • {profile?.email}</Text>
|
||||
<View style={[styles.badge, { backgroundColor: `${theme.colors.success}15` }]}>
|
||||
<View style={[styles.statusDot, { backgroundColor: theme.colors.success }]} />
|
||||
<Text style={[styles.badgeText, { color: theme.colors.success }]}>Active Agent</Text>
|
||||
</View>
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View entering={FadeInUp.delay(100)}>
|
||||
<Text style={[styles.sectionTitle, { color: theme.colors.textMuted }]}>Account Settings</Text>
|
||||
<View style={[styles.settingsGroup, { backgroundColor: theme.colors.surface, borderColor: theme.colors.cardBorder }]}>
|
||||
<SettingsRow
|
||||
icon="key-outline"
|
||||
label="Change Password"
|
||||
onPress={() => navigation.navigate('AgentChangePassword')}
|
||||
/>
|
||||
<View style={[styles.divider, { backgroundColor: theme.colors.cardBorder }]} />
|
||||
<SettingsRow
|
||||
icon="chatbubble-ellipses-outline"
|
||||
label="SMS Log"
|
||||
onPress={() => navigation.navigate('SmsHistory')}
|
||||
/>
|
||||
<View style={[styles.divider, { backgroundColor: theme.colors.cardBorder }]} />
|
||||
<SettingsRow
|
||||
icon="notifications-outline"
|
||||
label="Notification Settings"
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View entering={FadeInUp.delay(200)}>
|
||||
<Text style={[styles.sectionTitle, { color: theme.colors.textMuted, marginTop: 24 }]}>Support & Legal</Text>
|
||||
<View style={[styles.settingsGroup, { backgroundColor: theme.colors.surface, borderColor: theme.colors.cardBorder }]}>
|
||||
<SettingsRow
|
||||
icon="help-circle-outline"
|
||||
label="Help & Support"
|
||||
onPress={() => {}}
|
||||
/>
|
||||
<View style={[styles.divider, { backgroundColor: theme.colors.cardBorder }]} />
|
||||
<SettingsRow
|
||||
icon="document-text-outline"
|
||||
label="Terms & Conditions"
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</Animated.View>
|
||||
|
||||
<View style={{ marginTop: 32 }}>
|
||||
<Button
|
||||
title="Log Out"
|
||||
variant="secondary"
|
||||
onPress={handleLogout}
|
||||
style={{ borderColor: theme.colors.danger, borderWidth: 1 }}
|
||||
textStyle={{ color: theme.colors.danger }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.footerInfo}>
|
||||
<Text style={[styles.version, { color: theme.colors.textMuted }]}>App Version 1.0.0</Text>
|
||||
<Text style={[styles.version, { color: theme.colors.textMuted }]}>Agent Module v1</Text>
|
||||
</View>
|
||||
|
||||
</ScrollView>
|
||||
</ScreenShell>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scrollContent: {
|
||||
padding: 16,
|
||||
paddingBottom: TAB_BAR_HEIGHT + 16,
|
||||
},
|
||||
profileCard: {
|
||||
alignItems: 'center',
|
||||
padding: 24,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
marginBottom: 24,
|
||||
},
|
||||
avatarBig: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: 40,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
avatarText: {
|
||||
fontSize: 32,
|
||||
fontWeight: '800',
|
||||
},
|
||||
name: {
|
||||
fontSize: 20,
|
||||
fontWeight: '800',
|
||||
marginBottom: 4,
|
||||
},
|
||||
role: {
|
||||
fontSize: 14,
|
||||
marginBottom: 12,
|
||||
},
|
||||
badge: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 12,
|
||||
gap: 6,
|
||||
},
|
||||
statusDot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
},
|
||||
badgeText: {
|
||||
fontSize: 12,
|
||||
fontWeight: '700',
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 0.5,
|
||||
marginBottom: 8,
|
||||
marginLeft: 8,
|
||||
},
|
||||
settingsGroup: {
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
settingsRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
},
|
||||
settingsRowLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
},
|
||||
settingsIconFrame: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
settingsLabel: {
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
},
|
||||
divider: {
|
||||
height: 1,
|
||||
marginLeft: 64, // Align with text
|
||||
},
|
||||
footerInfo: {
|
||||
alignItems: 'center',
|
||||
marginTop: 32,
|
||||
gap: 4,
|
||||
},
|
||||
version: {
|
||||
fontSize: 12,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user