116 lines
4.1 KiB
TypeScript
116 lines
4.1 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { View, StyleSheet, FlatList, RefreshControl, Text } from 'react-native';
|
|
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
|
import Animated, { FadeInUp } from 'react-native-reanimated';
|
|
|
|
import { ScreenShell } from '../../../components';
|
|
import { useTheme, fontFamily } from '../../../theme';
|
|
import { useAppDispatch, useAppSelector } from '../../../app/hooks';
|
|
import type { AgentCollectionsStackParamList } from '../navigation/agentNavigationTypes';
|
|
import { useGetCollectionHistoryQuery } from '../services/agentApi';
|
|
import { agentActions } from '../store/agentSlice';
|
|
import { selectCollectionHistory } from '../store/agentSelectors';
|
|
|
|
import { CollectionEntryCard } from '../components/CollectionEntryCard';
|
|
import { AgentSkeletonLoader } from '../components/AgentSkeletonLoader';
|
|
import { AgentEmptyState } from '../components/AgentEmptyState';
|
|
import { formatAgentCurrency, formatDate } from '../utils/agentFormatters';
|
|
|
|
type Props = NativeStackScreenProps<AgentCollectionsStackParamList, 'CollectionHistory'>;
|
|
|
|
export default function CollectionHistoryScreen({ navigation }: Props) {
|
|
const theme = useTheme();
|
|
const dispatch = useAppDispatch();
|
|
|
|
const history = useAppSelector(selectCollectionHistory);
|
|
|
|
const { data, isLoading, refetch, isFetching } = useGetCollectionHistoryQuery({});
|
|
|
|
useEffect(() => {
|
|
if (data) {
|
|
dispatch(agentActions.setCollectionHistory(data));
|
|
}
|
|
}, [data, dispatch]);
|
|
|
|
const totalCollected = history.reduce((sum, item) => sum + item.collectedAmount, 0);
|
|
|
|
return (
|
|
<ScreenShell title="Collection History" scrollable={false}>
|
|
{/* Summary Header */}
|
|
<View style={[styles.summaryHeader, { backgroundColor: theme.colors.surface, borderBottomColor: theme.colors.cardBorder }]}>
|
|
<View style={styles.summaryItem}>
|
|
<Text style={[styles.summaryLabel, { color: theme.colors.textMuted }]}>Total Entries</Text>
|
|
<Text style={[styles.summaryValue, { color: theme.colors.textPrimary }]}>{history.length}</Text>
|
|
</View>
|
|
<View style={[styles.vDivider, { backgroundColor: theme.colors.cardBorder }]} />
|
|
<View style={styles.summaryItem}>
|
|
<Text style={[styles.summaryLabel, { color: theme.colors.textMuted }]}>Amount Collected</Text>
|
|
<Text style={[styles.summaryValue, { color: theme.colors.primary }]}>{formatAgentCurrency(totalCollected)}</Text>
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.listArea}>
|
|
{isLoading && history.length === 0 ? (
|
|
<AgentSkeletonLoader type="list" />
|
|
) : (
|
|
<FlatList
|
|
data={history}
|
|
keyExtractor={item => item.id}
|
|
contentContainerStyle={styles.listContent}
|
|
showsVerticalScrollIndicator={false}
|
|
refreshControl={
|
|
<RefreshControl refreshing={isFetching} onRefresh={refetch} colors={[theme.colors.primary]} />
|
|
}
|
|
ListEmptyComponent={() => (
|
|
<AgentEmptyState
|
|
title="No history found"
|
|
description="There are no past collection records."
|
|
/>
|
|
)}
|
|
renderItem={({ item, index }) => (
|
|
<Animated.View entering={FadeInUp.delay(index * 50)}>
|
|
<CollectionEntryCard
|
|
entry={item}
|
|
onPress={() => item.status !== 'pending' && item.receiptId ? navigation.navigate('CollectionReceipt', { entryId: item.receiptId }) : null}
|
|
/>
|
|
</Animated.View>
|
|
)}
|
|
/>
|
|
)}
|
|
</View>
|
|
</ScreenShell>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
summaryHeader: {
|
|
flexDirection: 'row',
|
|
padding: 16,
|
|
borderBottomWidth: 1,
|
|
},
|
|
summaryItem: {
|
|
flex: 1,
|
|
},
|
|
summaryLabel: {
|
|
fontSize: 12,
|
|
fontFamily: fontFamily.medium,
|
|
marginBottom: 4,
|
|
},
|
|
summaryValue: {
|
|
fontSize: 20,
|
|
fontFamily: fontFamily.bold,
|
|
},
|
|
vDivider: {
|
|
width: 1,
|
|
height: '100%',
|
|
marginHorizontal: 16,
|
|
},
|
|
listArea: {
|
|
flex: 1,
|
|
},
|
|
listContent: {
|
|
padding: 16,
|
|
paddingBottom: 40,
|
|
},
|
|
});
|