Fix form keyboard issues and sticky footers in agent screens
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
import React from 'react';
|
||||
import { FlatList, ScrollView, StyleSheet, Text, View, Pressable } from 'react-native';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
|
||||
import { Input, ScreenShell } from '../../../components';
|
||||
import { ServicesStackParamList } from '../../../navigation/types';
|
||||
import { useTheme } from '../../../theme';
|
||||
import { AwarenessCard } from '../components/AwarenessCard';
|
||||
import { useAwareness } from '../hooks/useAwareness';
|
||||
import { AwarenessCategory } from '../types';
|
||||
|
||||
type Props = NativeStackScreenProps<ServicesStackParamList, 'AwarenessList'>;
|
||||
|
||||
const CATEGORIES: (AwarenessCategory | 'All')[] = ['All', 'RBI', 'NPCI', 'Fraud Alert', 'Best Practices'];
|
||||
|
||||
export default function AwarenessListScreen({ navigation }: Props) {
|
||||
const theme = useTheme();
|
||||
const { articles, filter, setFilter, bookmarks, toggleBookmark, urgentArticles } = useAwareness();
|
||||
|
||||
const handleSearch = (query: string) => {
|
||||
setFilter({ ...filter, searchQuery: query });
|
||||
};
|
||||
|
||||
const handleCategoryPress = (category: AwarenessCategory | 'All') => {
|
||||
setFilter({ ...filter, category });
|
||||
};
|
||||
|
||||
return (
|
||||
<ScreenShell title="Security aware" subtitle="Learn to protect your digital banking">
|
||||
<View style={styles.searchContainer}>
|
||||
<Input
|
||||
placeholder="Search safety tips, fraud alerts..."
|
||||
value={filter.searchQuery}
|
||||
onChangeText={handleSearch}
|
||||
leftAccessory={<Ionicons name="search-outline" size={20} color={theme.colors.textMuted} />}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.filterWrapper}>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.filterContainer}>
|
||||
{CATEGORIES.map((cat) => {
|
||||
const isActive = filter.category === cat;
|
||||
return (
|
||||
<Pressable
|
||||
key={cat}
|
||||
onPress={() => handleCategoryPress(cat)}
|
||||
style={[
|
||||
styles.filterChip,
|
||||
{
|
||||
backgroundColor: isActive ? theme.colors.primary : theme.colors.surfaceMuted,
|
||||
borderColor: isActive ? theme.colors.primary : theme.colors.cardBorder,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.filterText,
|
||||
{ color: isActive ? theme.colors.white : theme.colors.textSecondary },
|
||||
]}
|
||||
>
|
||||
{cat}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
<FlatList
|
||||
data={articles}
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => (
|
||||
<AwarenessCard
|
||||
article={item}
|
||||
isBookmarked={bookmarks.includes(item.id)}
|
||||
onToggleBookmark={() => toggleBookmark(item.id)}
|
||||
onPress={() => navigation.navigate('AwarenessDetail', { articleId: item.id })}
|
||||
/>
|
||||
)}
|
||||
ListHeaderComponent={
|
||||
<>
|
||||
{urgentArticles.length > 0 && filter.category === 'All' && filter.searchQuery === '' && (
|
||||
<View style={styles.urgentSection}>
|
||||
<View style={styles.sectionHeader}>
|
||||
<Ionicons name="alert-circle" size={18} color={theme.colors.error} />
|
||||
<Text style={[styles.sectionTitle, { color: theme.colors.textPrimary }]}>
|
||||
Critical Security Alerts
|
||||
</Text>
|
||||
</View>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.urgentCarousel}>
|
||||
{urgentArticles.map((article) => (
|
||||
<Pressable
|
||||
key={article.id}
|
||||
onPress={() => navigation.navigate('AwarenessDetail', { articleId: article.id })}
|
||||
style={[styles.urgentCard, { backgroundColor: `${theme.colors.error}08`, borderColor: `${theme.colors.error}20` }]}
|
||||
>
|
||||
<View style={[styles.urgentIcon, { backgroundColor: `${theme.colors.error}15` }]}>
|
||||
<Ionicons name={article.icon as any} size={20} color={theme.colors.error} />
|
||||
</View>
|
||||
<Text style={[styles.urgentCardTitle, { color: theme.colors.textPrimary }]} numberOfLines={1}>
|
||||
{article.title}
|
||||
</Text>
|
||||
<Text style={[styles.urgentCardDesc, { color: theme.colors.textSecondary }]} numberOfLines={1}>
|
||||
{article.description}
|
||||
</Text>
|
||||
</Pressable>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.sectionHeader}>
|
||||
<Text style={[styles.sectionTitle, { color: theme.colors.textPrimary }]}>
|
||||
{filter.category === 'All' ? 'Latest Awareness Articles' : `${filter.category} Guidelines`}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
}
|
||||
contentContainerStyle={styles.listContent}
|
||||
ListEmptyComponent={
|
||||
<View style={styles.emptyContainer}>
|
||||
<Ionicons name="search-outline" size={48} color={theme.colors.textMuted} />
|
||||
<Text style={[styles.emptyTitle, { color: theme.colors.textPrimary }]}>No results found</Text>
|
||||
<Text style={[styles.emptySubtitle, { color: theme.colors.textSecondary }]}>
|
||||
Try adjusting your search or filters to find what you're looking for.
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
scrollEnabled={false} // Since it's inside ScreenShell's ScrollView
|
||||
/>
|
||||
</ScreenShell>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
searchContainer: {
|
||||
paddingHorizontal: 16,
|
||||
marginBottom: 16,
|
||||
},
|
||||
filterWrapper: {
|
||||
marginBottom: 20,
|
||||
},
|
||||
filterContainer: {
|
||||
paddingHorizontal: 16,
|
||||
gap: 10,
|
||||
},
|
||||
filterChip: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 20,
|
||||
borderWidth: 1,
|
||||
},
|
||||
filterText: {
|
||||
fontSize: 13,
|
||||
fontWeight: '700',
|
||||
},
|
||||
listContent: {
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
urgentSection: {
|
||||
marginBottom: 24,
|
||||
gap: 12,
|
||||
},
|
||||
sectionHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
marginBottom: 12,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: '800',
|
||||
letterSpacing: -0.3,
|
||||
},
|
||||
urgentCarousel: {
|
||||
gap: 12,
|
||||
},
|
||||
urgentCard: {
|
||||
width: 260,
|
||||
padding: 16,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
gap: 8,
|
||||
},
|
||||
urgentIcon: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
urgentCardTitle: {
|
||||
fontSize: 15,
|
||||
fontWeight: '700',
|
||||
},
|
||||
urgentCardDesc: {
|
||||
fontSize: 12,
|
||||
},
|
||||
emptyContainer: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 60,
|
||||
gap: 12,
|
||||
},
|
||||
emptyTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '800',
|
||||
},
|
||||
emptySubtitle: {
|
||||
fontSize: 14,
|
||||
textAlign: 'center',
|
||||
paddingHorizontal: 40,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user