Fix form keyboard issues and sticky footers in agent screens
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import type { CompositeScreenProps } from '@react-navigation/native';
|
||||
import type { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
|
||||
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import Ionicons from '@react-native-vector-icons/ionicons';
|
||||
|
||||
import { useAppSelector } from '../../../app/hooks';
|
||||
import { Card, ScreenShell } from '../../../components';
|
||||
import { useToast } from '../../../hooks/useToast';
|
||||
import { ServiceGridItem } from '../../home/components/ServiceGridItem';
|
||||
import { ServiceStatusPill } from '../components/ServiceStatusPill';
|
||||
import { selectServiceRequests } from '../store/serviceSelectors';
|
||||
import type { MainTabParamList, ServicesStackParamList } from '../../../navigation/types';
|
||||
import { useTheme } from '../../../theme';
|
||||
|
||||
type Props = CompositeScreenProps<
|
||||
NativeStackScreenProps<ServicesStackParamList, 'ServicesHub'>,
|
||||
BottomTabScreenProps<MainTabParamList, 'Services'>
|
||||
>;
|
||||
|
||||
export default function ServicesHubScreen({ navigation }: Props) {
|
||||
const theme = useTheme();
|
||||
const toast = useToast();
|
||||
const serviceRequests = useAppSelector(selectServiceRequests);
|
||||
|
||||
const latestRequest = serviceRequests[0] ?? null;
|
||||
const openRequestsCount = serviceRequests.filter(
|
||||
(request) => request.status !== 'resolved',
|
||||
).length;
|
||||
|
||||
const serviceOptions = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'branch_locator',
|
||||
title: 'Find Branch & ATMs',
|
||||
icon: 'map-outline',
|
||||
iconColor: '#10B981',
|
||||
onPress: () => navigation.navigate('BranchLocator'),
|
||||
},
|
||||
{
|
||||
id: 'all_deposits',
|
||||
title: 'Deposits',
|
||||
icon: 'wallet-outline',
|
||||
iconColor: '#124577',
|
||||
onPress: () => navigation.navigate('DepositsOverview'),
|
||||
},
|
||||
{
|
||||
id: 'cheque_services',
|
||||
title: 'Cheque Services',
|
||||
icon: 'book-outline',
|
||||
iconColor: '#3B82F6',
|
||||
onPress: () => navigation.navigate('ChequeServicesHub'),
|
||||
},
|
||||
{
|
||||
id: 'certificates',
|
||||
title: 'Certificates',
|
||||
icon: 'document-text-outline',
|
||||
iconColor: '#F59E0B',
|
||||
onPress: () => navigation.navigate('CertificatesHub'),
|
||||
},
|
||||
{
|
||||
id: 'requests',
|
||||
title: 'Service Requests',
|
||||
icon: 'git-pull-request-outline',
|
||||
iconColor: '#EF4444',
|
||||
onPress: () => navigation.navigate('ServiceRequestsHub'),
|
||||
},
|
||||
{
|
||||
id: 'calculator',
|
||||
title: 'FD/RD Calc',
|
||||
icon: 'calculator-outline',
|
||||
iconColor: '#6366F1',
|
||||
onPress: () => navigation.navigate('DepositCalculator'),
|
||||
},
|
||||
{
|
||||
id: 'support',
|
||||
title: 'Support Chat',
|
||||
icon: 'chatbubble-ellipses-outline',
|
||||
iconColor: '#0EA5E9',
|
||||
onPress: () =>
|
||||
toast(
|
||||
'Support chat screen pending',
|
||||
'info',
|
||||
'This feature is coming in the next update.',
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'help',
|
||||
title: 'Help Center',
|
||||
icon: 'help-circle-outline',
|
||||
iconColor: '#8B5CF6',
|
||||
onPress: () =>
|
||||
toast('Help center pending', 'info', 'Coming soon.'),
|
||||
},
|
||||
{
|
||||
id: 'cyber_security',
|
||||
title: 'Cyber Security',
|
||||
icon: 'shield-half-outline',
|
||||
iconColor: '#F59E0B',
|
||||
onPress: () => navigation.navigate('AwarenessList'),
|
||||
},
|
||||
{
|
||||
id: 'protection_schemes',
|
||||
title: 'Protection & Schemes',
|
||||
icon: 'umbrella-outline',
|
||||
iconColor: '#EC4899',
|
||||
onPress: () => navigation.navigate('FinancialProtectionMain'),
|
||||
},
|
||||
],
|
||||
[navigation, toast]
|
||||
);
|
||||
|
||||
return (
|
||||
<ScreenShell title="Service desk" subtitle="All service options in one hub">
|
||||
{/* <View style={styles.sectionHeader}>
|
||||
<Text style={[styles.sectionTitle, { color: theme.colors.textPrimary }]}>
|
||||
Service options
|
||||
</Text>
|
||||
<Text style={[styles.sectionSubtitle, { color: theme.colors.textSecondary }]}>
|
||||
Choose a service card to continue
|
||||
</Text>
|
||||
</View> */}
|
||||
|
||||
<View style={styles.grid}>
|
||||
{serviceOptions.map((option) => (
|
||||
<ServiceGridItem
|
||||
key={option.id}
|
||||
id={option.id}
|
||||
title={option.title}
|
||||
icon={option.icon}
|
||||
iconColor={option.iconColor}
|
||||
onPress={option.onPress}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<Card variant="glass" style={styles.heroCard}>
|
||||
<View style={styles.heroHeader}>
|
||||
<View
|
||||
style={[
|
||||
styles.heroIcon,
|
||||
{ backgroundColor: `${theme.colors.primary}12` },
|
||||
]}
|
||||
>
|
||||
<Ionicons name="grid-outline" size={18} color={theme.colors.primary} />
|
||||
</View>
|
||||
<View style={styles.heroCopy}>
|
||||
<Text style={[styles.heroTitle, { color: theme.colors.textPrimary }]}>
|
||||
Services hub
|
||||
</Text>
|
||||
<Text style={[styles.heroSubtitle, { color: theme.colors.textSecondary }]}>
|
||||
Browse deposit journeys, service support actions, and request tools from one place.
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.heroStats}>
|
||||
<View style={[styles.heroStat, { backgroundColor: theme.colors.surfaceMuted }]}>
|
||||
<Text style={[styles.heroStatLabel, { color: theme.colors.textSecondary }]}>
|
||||
Open requests
|
||||
</Text>
|
||||
<Text style={[styles.heroStatValue, { color: theme.colors.textPrimary }]}>
|
||||
{openRequestsCount}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[styles.heroStat, { backgroundColor: theme.colors.surfaceMuted }]}>
|
||||
<Text style={[styles.heroStatLabel, { color: theme.colors.textSecondary }]}>
|
||||
Latest status
|
||||
</Text>
|
||||
{latestRequest ? (
|
||||
<ServiceStatusPill status={latestRequest.status} />
|
||||
) : (
|
||||
<Text style={[styles.heroStatEmpty, { color: theme.colors.textMuted }]}>
|
||||
No requests
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</Card>
|
||||
<View style={styles.bottomSpacer} />
|
||||
</ScreenShell>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
heroCard: {
|
||||
gap: 16,
|
||||
shadowOpacity: 0.04,
|
||||
shadowRadius: 14,
|
||||
elevation: 2,
|
||||
},
|
||||
heroHeader: {
|
||||
flexDirection: 'row',
|
||||
gap: 12,
|
||||
},
|
||||
heroIcon: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius: 14,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
heroCopy: {
|
||||
flex: 1,
|
||||
gap: 4,
|
||||
},
|
||||
heroTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '800',
|
||||
},
|
||||
heroSubtitle: {
|
||||
fontSize: 13,
|
||||
lineHeight: 18,
|
||||
},
|
||||
heroStats: {
|
||||
flexDirection: 'row',
|
||||
gap: 12,
|
||||
},
|
||||
heroStat: {
|
||||
flex: 1,
|
||||
borderRadius: 18,
|
||||
padding: 14,
|
||||
gap: 6,
|
||||
},
|
||||
heroStatLabel: {
|
||||
fontSize: 11,
|
||||
fontWeight: '700',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
heroStatValue: {
|
||||
fontSize: 22,
|
||||
fontWeight: '900',
|
||||
letterSpacing: -0.5,
|
||||
},
|
||||
heroStatEmpty: {
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
},
|
||||
sectionHeader: {
|
||||
gap: 4,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '800',
|
||||
},
|
||||
sectionSubtitle: {
|
||||
fontSize: 13,
|
||||
lineHeight: 18,
|
||||
},
|
||||
grid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
bottomSpacer: {
|
||||
height: 60,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user