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,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,
},
});