Files
circle-collect/src/screens/ContributionScreen.tsx
T

152 lines
4.1 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import {
View,
Text,
StyleSheet,
Animated,
Easing,
} from 'react-native';
import LucideIcon from '../components/common/LucideIcon';
import CustomModal from '../components/common/CustomModal';
import { responsiveFontSize } from 'react-native-responsive-dimensions';
import { useTheme } from '../hooks/ui/useTheme';
import FontsFamily from '../constents/FontsFamily';
interface ContributionProps {
data: any;
visible: boolean;
onClose: () => void;
onConfirm: () => void;
}
const ContributionDetails: React.FC<ContributionProps> = ({
data,
visible,
onClose,
onConfirm,
}) => {
const theme = useTheme();
// Animations
const fadeAnim = useRef(new Animated.Value(0)).current;
const slideAnim = useRef(new Animated.Value(20)).current;
useEffect(() => {
if (visible) {
Animated.parallel([
Animated.timing(fadeAnim, {
toValue: 1,
duration: 400,
useNativeDriver: true,
}),
Animated.timing(slideAnim, {
toValue: 0,
duration: 400,
easing: Easing.out(Easing.quad),
useNativeDriver: true,
}),
]).start();
} else {
fadeAnim.setValue(0);
slideAnim.setValue(20);
}
}, [visible]);
return (
<CustomModal
visible={visible}
onClose={onClose}
onConfirm={onConfirm}
confirmText="Contribute Now"
title="Contribution Summary"
>
<Animated.View style={{ opacity: fadeAnim, transform: [{ translateY: slideAnim }] }}>
{/* Info Card */}
<View style={[styles.card, { backgroundColor: theme.colors.background, borderColor: theme.colors.border }]}>
<View style={styles.headerRow}>
<LucideIcon name="wallet-outline" size={24} color={theme.colors.primary} />
<Text style={[styles.amount, { color: theme.colors.textPrimary }]}>₹{data?.totalPayable || data?.baseAmount}</Text>
</View>
<View style={styles.infoGrid}>
<InfoItem label="Base Amount" value={`₹${data?.baseAmount}`} />
<InfoItem label="Due Date" value={data?.dueDate} />
<InfoItem label="Cycle End" value={data?.cycleEnd} />
<InfoItem label="Late Fee" value={`₹${data?.effectiveLateFee || 0}`} />
</View>
</View>
{/* Status Card */}
<View style={[styles.miniCard, { backgroundColor: theme.colors.background, borderColor: theme.colors.border }]}>
<Text style={[styles.label, { color: theme.colors.textMuted }]}>Cycle {data?.cycleNumber}</Text>
{data?.alreadyPaid && (
<Text style={[styles.statusText, { color: theme.colors.primary }]}>Payment Already Completed</Text>
)}
</View>
</Animated.View>
</CustomModal>
);
};
const InfoItem = ({ label, value }: { label: string; value: string | number }) => {
const theme = useTheme();
return (
<View style={styles.infoItem}>
<Text style={[styles.label, { color: theme.colors.textMuted }]}>{label}</Text>
<Text style={[styles.value, { color: theme.colors.textSecondary }]}>{value}</Text>
</View>
);
};
export default ContributionDetails;
const styles = StyleSheet.create({
card: {
padding: 20,
borderRadius: 16,
borderWidth: 1,
marginBottom: 12,
},
headerRow: {
flexDirection: 'row',
alignItems: 'center',
gap: 12,
marginBottom: 20,
},
amount: {
fontSize: responsiveFontSize(2.8),
fontFamily: FontsFamily.nunitoBold,
},
infoGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 16,
},
infoItem: {
width: '45%',
},
miniCard: {
padding: 16,
borderRadius: 12,
borderWidth: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
label: {
fontSize: responsiveFontSize(1.2),
fontFamily: FontsFamily.nunitoMedium,
textTransform: 'uppercase',
letterSpacing: 0.5,
},
value: {
fontSize: responsiveFontSize(1.6),
fontFamily: FontsFamily.nunitoBold,
marginTop: 2,
},
statusText: {
fontSize: responsiveFontSize(1.4),
fontFamily: FontsFamily.nunitoBold,
},
});