import React, { FC } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, ToastAndroid } from 'react-native'; import { useNavigation } from '@react-navigation/native'; import { responsiveFontSize } from 'react-native-responsive-dimensions'; import { useTheme } from '../hooks/ui/useTheme'; import { useFetch } from '../hooks/core/useFetch'; import { useCreate } from '../hooks/core/useCreate'; import { CONTRIBUTE } from '../utils/ApiUrls'; import FontsFamily from '../constents/FontsFamily'; interface JoinedGroup { id: string; groupName: string; description: string; visibility: 'PUBLIC' | 'PRIVATE'; createdByUserId: number; createdByName: string; startDate: string | null; endDate: string | null; minParticipants: number; maxParticipants: number; currentParticipants: number; contributionAmount: number; cycleType: 'MONTHLY' | 'WEEKLY' | 'QUARTERLY' | 'CUSTOM'; status: 'ACTIVE' | 'PENDING' | 'COMPLETED'| 'APPROVED'; } interface JoinedGroupCardProps { item: JoinedGroup; hasPaid?: boolean; } const formatDate = (dateStr: string | null): string => { if (!dateStr) return 'N/A'; const [year, month, day] = dateStr.split('-'); const months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; const monthIndex = parseInt(month, 10) - 1; const dayNum = parseInt(day, 10); return `${dayNum} ${months[monthIndex]} ${year}`; }; export const JoinedGroupCard: FC = ({ item }:any) => { const theme = useTheme(); const navigation = useNavigation(); console.log("item",item) const { data: payableRes } = useFetch(`${CONTRIBUTE}${item.id}/calculate-contribution`); const payable = payableRes?.data; const { mutate: contribute, isPending: loading } = useCreate( `payments/contribute/${item?.id}?amount=${payable?.totalPayable}`, { onSuccess: () => { ToastAndroid.show('Payment successful!', ToastAndroid.SHORT); }, onError: () => { ToastAndroid.show('Payment failed. Please try again.', ToastAndroid.SHORT); }, } ); const getStatusColors = (status: JoinedGroup['status']) => { switch (status) { case 'ACTIVE': return { bg: theme.palette.greyExtraLight, text: theme.palette.black }; case 'COMPLETED': return { bg: theme.palette.greyLight, text: theme.palette.greyDark }; default: return { bg: theme.palette.greyExtraLight, text: theme.palette.greyDark }; } }; const statusColors = getStatusColors(item.status); return ( navigation.navigate('GroupDetails', { item })} activeOpacity={0.7} > {item.groupName} by {item.createdByName} {item.status} {/* Contribution Amount — always visible */} Contribution UGX {item.contributionAmount.toLocaleString()} Duration {`${item?.cycleType} (${item?.customCycleDays} days)`} {/* Payment Details — shown when NOT paid and there's an amount due */} {payable && !payable.hasPaid && payable.totalPayable > 0 && ( Total Payable UGX {payable.totalPayable.toLocaleString()} {payable.effectiveLateFee > 0 && ( Late Fee + UGX {payable.effectiveLateFee.toLocaleString()} )} {payable.alreadyPaid > 0 && ( Already Paid UGX {payable.alreadyPaid.toLocaleString()} )} )} {formatDate(item.startDate)} — {formatDate(item.endDate)} {payable?.hasPaid ? ( ✓ PAID ) : ( item.status !== 'COMPLETED' && ( { navigation.navigate('PaymentMode' as any, { groupId: item.id, routeFrom: 'GroupDetails' }) }} disabled={loading} > {loading ? '...' : 'Pay'} ) )} ); }; const styles = StyleSheet.create({ card: { borderRadius: 16, padding: 14, marginBottom: 12, marginHorizontal: 12, borderWidth: 1, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 8, elevation: 2, }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 10, }, titleContainer: { flex: 1, }, groupName: { fontSize: responsiveFontSize(2), fontFamily: FontsFamily.nunitoExtraBold, marginBottom: 2, }, createdBy: { fontSize: responsiveFontSize(1.4), fontFamily: FontsFamily.nunitoRegular, }, statusBadge: { paddingHorizontal: 8, paddingVertical: 4, borderRadius: 6, }, statusText: { fontSize: responsiveFontSize(1.2), fontFamily: FontsFamily.nunitoBold, }, infoRow: { flexDirection: 'row', paddingVertical: 10, borderTopWidth: 1, borderBottomWidth: 1, marginBottom: 10, }, infoItem: { flex: 1, }, infoLabel: { fontSize: responsiveFontSize(1.3), fontFamily: FontsFamily.nunitoRegular, marginBottom: 2, }, infoValue: { fontSize: responsiveFontSize(1.6), fontFamily: FontsFamily.nunitoBold, }, payableSection: { marginBottom: 12, gap: 6, }, payableRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, payableLabel: { fontSize: responsiveFontSize(1.35), fontFamily: FontsFamily.nunitoSemiBold, }, payableValue: { fontSize: responsiveFontSize(1.5), fontFamily: FontsFamily.nunitoBold, }, footer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: 4, }, dateText: { fontSize: responsiveFontSize(1.3), fontFamily: FontsFamily.nunitoMedium, }, payButton: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 8, minWidth: 80, alignItems: 'center', }, payButtonText: { fontSize: responsiveFontSize(1.5), fontFamily: FontsFamily.nunitoBold, }, paidBadge: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 6, }, paidText: { fontSize: responsiveFontSize(1.3), fontFamily: FontsFamily.nunitoBold, letterSpacing: 0.5, }, });