1- import React , { useState , useEffect , useContext } from 'react' ;
2- import { View , StyleSheet , FlatList , Alert } from 'react-native' ;
3- import { Text , Appbar , List , Divider , ActivityIndicator } from 'react-native-paper' ;
4- import { AuthContext } from '../context/AuthContext' ;
5- import { getGroups , getGroupDetails } from '../api/groups' ;
61import { useIsFocused } from '@react-navigation/native' ;
2+ import { useContext , useEffect , useState } from 'react' ;
3+ import { Alert , FlatList , StyleSheet , View } from 'react-native' ;
4+ import { ActivityIndicator , Appbar , Divider , List , Text } from 'react-native-paper' ;
5+ import { getGroupDetails , getGroups } from '../api/groups' ;
6+ import { AuthContext } from '../context/AuthContext' ;
7+ import { calculateFriendBalances } from '../utils/balanceCalculator' ;
78
89const FriendsScreen = ( ) => {
910 const { token, user } = useContext ( AuthContext ) ;
1011 const [ friends , setFriends ] = useState ( [ ] ) ;
1112 const [ isLoading , setIsLoading ] = useState ( true ) ;
1213 const isFocused = useIsFocused ( ) ;
1314
14- const calculateFriendBalances = ( groupsWithDetails ) => {
15- const balances = { } ; // { friendId: { name, netBalance, groups: { groupId: { name, balance } } } }
16-
17- groupsWithDetails . forEach ( group => {
18- const [ membersResponse , expensesResponse ] = group . details ;
19- const members = membersResponse . data ;
20- const expenses = expensesResponse . data . expenses ;
21-
22- if ( ! expenses ) return ; // Guard against undefined expenses
23-
24- expenses . forEach ( expense => {
25- const payerId = expense . createdBy ;
26- const payerIsMe = payerId === user . _id ;
27-
28- expense . splits . forEach ( split => {
29- const memberId = split . userId ;
30- const memberIsMe = memberId === user . _id ;
31-
32- if ( memberId === payerId ) return ; // Payer doesn't owe themselves
33-
34- if ( payerIsMe && ! memberIsMe ) { // I paid, they owe me
35- if ( ! balances [ memberId ] ) balances [ memberId ] = { name : members . find ( m => m . userId === memberId ) ?. user . name || 'Unknown' , netBalance : 0 , groups : { } } ;
36- if ( ! balances [ memberId ] . groups [ group . id ] ) balances [ memberId ] . groups [ group . id ] = { name : group . name , balance : 0 } ;
37- balances [ memberId ] . netBalance += split . amount ;
38- balances [ memberId ] . groups [ group . id ] . balance += split . amount ;
39- } else if ( ! payerIsMe && memberIsMe ) { // They paid, I owe them
40- if ( ! balances [ payerId ] ) balances [ payerId ] = { name : members . find ( m => m . userId === payerId ) ?. user . name || 'Unknown' , netBalance : 0 , groups : { } } ;
41- if ( ! balances [ payerId ] . groups [ group . id ] ) balances [ payerId ] . groups [ group . id ] = { name : group . name , balance : 0 } ;
42- balances [ payerId ] . netBalance -= split . amount ;
43- balances [ payerId ] . groups [ group . id ] . balance -= split . amount ;
44- }
45- } ) ;
46- } ) ;
47- } ) ;
48-
49- // Format the data for the UI
50- const formattedFriends = Object . entries ( balances ) . map ( ( [ id , data ] ) => ( {
51- id,
52- name : data . name ,
53- netBalance : data . netBalance ,
54- groups : Object . entries ( data . groups ) . map ( ( [ groupId , groupData ] ) => ( {
55- id : groupId ,
56- name : groupData . name ,
57- balance : groupData . balance ,
58- } ) ) ,
59- } ) ) ;
60-
61- setFriends ( formattedFriends ) ;
62- } ;
63-
6415 useEffect ( ( ) => {
6516 const fetchData = async ( ) => {
6617 setIsLoading ( true ) ;
@@ -75,7 +26,9 @@ const FriendsScreen = () => {
7526 } )
7627 ) ;
7728
78- calculateFriendBalances ( groupsWithDetails ) ;
29+ // Use the utility function to calculate friend balances
30+ const calculatedFriends = calculateFriendBalances ( groupsWithDetails , user . _id ) ;
31+ setFriends ( calculatedFriends ) ;
7932
8033 } catch ( error ) {
8134 console . error ( 'Failed to fetch data for friends screen:' , error ) ;
0 commit comments