@@ -9,21 +9,51 @@ import { useAppTheme } from '../theme/useAppTheme';
99import { spacing } from '../theme/spacing' ;
1010import { BalanceCard } from '../components/BalanceCard' ;
1111import { SectionHeader } from '../components/SectionHeader' ;
12- import { ActivityItem } from '../components/ActivityItem' ;
13- import { Button } from '../components/ui/Button' ;
1412import { Avatar } from '../components/ui/Avatar' ;
13+ import { groupService } from '../services/group.service' ;
14+ import type { ActivityDto } from '@fairshare/shared-types' ;
15+ import { useToastStore } from '../store/toastStore' ;
1516
1617export function HomeScreen ( { navigation } : { navigation : any } ) {
1718 const user = useAuthStore ( ( state ) => state . user ) ;
1819 const groups = useGroupStore ( ( state ) => state . groups ) ;
1920 const { colors, typography } = useAppTheme ( ) ;
21+ const [ summary , setSummary ] = React . useState < { totalBalanceCents : string } | null > ( null ) ;
22+ const [ activities , setActivities ] = React . useState < ActivityDto [ ] > ( [ ] ) ;
23+ const [ loading , setLoading ] = React . useState ( true ) ;
24+ const toast = useToastStore ( ( state ) => state . show ) ;
25+
26+ const loadData = React . useCallback ( async ( ) => {
27+ try {
28+ const [ summaryData , activityData ] = await Promise . all ( [
29+ groupService . userSummary ( ) ,
30+ groupService . userActivity ( 0 , 5 ) ,
31+ ] ) ;
32+ setSummary ( summaryData ) ;
33+ setActivities ( activityData . items ) ;
34+ } catch ( err ) {
35+ console . error ( err ) ;
36+ toast ( 'Failed to sync your vibes' ) ;
37+ } finally {
38+ setLoading ( false ) ;
39+ }
40+ } , [ toast ] ) ;
41+
42+ React . useEffect ( ( ) => {
43+ void loadData ( ) ;
44+ } , [ loadData ] ) ;
2045
2146 const quickActions = [
22- { label : 'Add Expense ' , icon : 'plus-circle-outline' as const , color : colors . primary , onPress : ( ) => navigation . navigate ( 'AddExpense' , { groupId : groups [ 0 ] ?. id ?? '' } ) } ,
23- { label : 'Groups ' , icon : 'account-group-outline' as const , color : colors . accent , onPress : ( ) => navigation . navigate ( 'Groups' ) } ,
24- { label : 'Settle Up ' , icon : 'handshake-outline' as const , color : colors . success , onPress : ( ) => navigation . navigate ( 'SettleUp' , { groupId : groups [ 0 ] ?. id ?? '' } ) } ,
47+ { label : 'Split it ' , icon : 'plus-circle-outline' as const , color : colors . primary , onPress : ( ) => navigation . navigate ( 'AddExpense' , { groupId : groups [ 0 ] ?. id ?? '' } ) } ,
48+ { label : 'Squads ' , icon : 'account-group-outline' as const , color : colors . accent , onPress : ( ) => navigation . navigate ( 'Groups' ) } ,
49+ { label : 'Clear Air ' , icon : 'handshake-outline' as const , color : colors . success , onPress : ( ) => navigation . navigate ( 'SettleUp' , { groupId : groups [ 0 ] ?. id ?? '' } ) } ,
2550 ] ;
2651
52+ const totalBalance = Number ( summary ?. totalBalanceCents ?? 0 ) / 100 ;
53+ const balanceLabel = totalBalance >= 0 ? 'Securing the bag' : 'Lowkey in debt' ;
54+ const balanceVariant = totalBalance >= 0 ? 'success' : 'danger' ;
55+ const balanceIcon = totalBalance >= 0 ? 'trending-up' : 'trending-down' ;
56+
2757 return (
2858 < ScrollView
2959 style = { { flex : 1 , backgroundColor : colors . background } }
@@ -33,8 +63,8 @@ export function HomeScreen({ navigation }: { navigation: any }) {
3363 { /* Header */ }
3464 < View style = { styles . header } >
3565 < View >
36- < Text style = { [ typography . bodyMedium , { color : colors . text_secondary } ] } > Welcome back, </ Text >
37- < Text style = { [ typography . h2 , { color : colors . text_primary , marginTop : 2 } ] } > { user ?. name ?? 'Friend ' } </ Text >
66+ < Text style = { [ typography . bodyMedium , { color : colors . text_secondary } ] } > Yo, welcome back ✌️ </ Text >
67+ < Text style = { [ typography . h2 , { color : colors . text_primary , marginTop : 2 } ] } > { user ?. name ?? 'Bestie ' } </ Text >
3868 </ View >
3969 < TouchableOpacity onPress = { ( ) => navigation . navigate ( 'Profile' ) } >
4070 < Avatar name = { user ?. name ?? 'U' } size = { 48 } />
@@ -44,16 +74,16 @@ export function HomeScreen({ navigation }: { navigation: any }) {
4474 { /* Balance Summary */ }
4575 < Animated . View entering = { FadeInDown . duration ( 400 ) } style = { styles . summarySection } >
4676 < BalanceCard
47- title = "Total Balance "
48- amount = "$420.69"
49- subtitle = "You are owed"
50- variant = "success"
51- icon = "trending-up"
77+ title = "The Bag 💰 "
78+ amount = { `$ ${ Math . abs ( totalBalance ) . toFixed ( 2 ) } ` }
79+ subtitle = { balanceLabel }
80+ variant = { balanceVariant }
81+ icon = { balanceIcon }
5282 />
5383 </ Animated . View >
5484
5585 { /* Quick Actions */ }
56- < SectionHeader title = "Quick Actions " />
86+ < SectionHeader title = "Fast Moves " />
5787 < View style = { styles . quickActions } >
5888 { quickActions . map ( ( action , i ) => (
5989 < Animated . View
@@ -77,25 +107,31 @@ export function HomeScreen({ navigation }: { navigation: any }) {
77107
78108 { /* Recent Activity */ }
79109 < SectionHeader
80- title = "Recent Activity "
110+ title = "The Tea ☕ "
81111 action = "See all"
82- onActionPress = { ( ) => { } }
112+ onActionPress = { ( ) => navigation . navigate ( 'Activity' ) }
83113 />
84114 < View style = { styles . activityList } >
85- { [ 1 , 2 , 3 ] . map ( ( item , i ) => (
86- < Animated . View
87- key = { item }
88- entering = { FadeInDown . duration ( 400 ) . delay ( 400 + i * 100 ) }
89- >
90- < ActivityItem
91- title = "Dinner at Joe's"
92- subtitle = "Paid by you in Trip to Bali"
93- amount = "$45.00"
94- date = "2h ago"
95- icon = "receipt"
96- />
97- </ Animated . View >
98- ) ) }
115+ { activities . length > 0 ? (
116+ activities . map ( ( activity , i ) => (
117+ < Animated . View
118+ key = { activity . id }
119+ entering = { FadeInDown . duration ( 400 ) . delay ( 400 + i * 100 ) }
120+ >
121+ < ActivityItem
122+ title = { activity . type . replace ( '_' , ' ' ) }
123+ subtitle = { `${ activity . actorUserId } in group` }
124+ amount = { activity . metadata ?. totalAmountCents ? `$${ ( Number ( activity . metadata . totalAmountCents ) / 100 ) . toFixed ( 2 ) } ` : undefined }
125+ date = { new Date ( activity . createdAt ) . toLocaleDateString ( ) }
126+ icon = "receipt"
127+ />
128+ </ Animated . View >
129+ ) )
130+ ) : (
131+ < Text style = { [ typography . bodyMedium , { color : colors . text_secondary , textAlign : 'center' , marginTop : spacing . lg } ] } >
132+ No tea to spill yet.
133+ </ Text >
134+ ) }
99135 </ View >
100136 </ ScrollView >
101137 ) ;
0 commit comments