Skip to content
This repository was archived by the owner on May 5, 2025. It is now read-only.

Commit edfcfaa

Browse files
committed
feat: create RecipientCard component for displaying recipient details
1 parent 3b27e0f commit edfcfaa

File tree

2 files changed

+182
-142
lines changed

2 files changed

+182
-142
lines changed

src/app/recipients/index.tsx

Lines changed: 95 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,112 @@
11
import { Ionicons } from '@expo/vector-icons';
2-
import {
3-
Pressable,
4-
ScrollView,
5-
StyleSheet,
6-
Text,
7-
TextInput,
8-
View,
9-
Image,
10-
} from 'react-native';
2+
import { Pressable, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';
113
import { SafeAreaView } from 'react-native-safe-area-context';
124
import { useRouter } from 'expo-router';
13-
145
import { Recipient } from '@/models/Recipient';
6+
import RecipientCard from '@/components/utils/RecipientCard';
157

168
const AllRecipientsScreen = () => {
17-
const router = useRouter();
9+
const router = useRouter();
1810

19-
const recipients: Recipient[] = [
20-
{ id: '1', image:'https://img.freepik.com/premium-vector/cute-boy-smiling-cartoon-kawaii-boy-illustration-boy-avatar-happy-kid_1001605-3445.jpg', name: 'Alex', budget: 2000, spent: 1500 },
21-
{ id: '2', image:'https://static.vecteezy.com/system/resources/previews/004/899/833/non_2x/beautiful-girl-with-blue-hair-avatar-of-woman-for-social-network-vector.jpg', name: 'Emily', budget: 2200, spent: 1600 },
22-
{ id: '3', image:'https://img.freepik.com/premium-vector/boy-with-blue-hoodie-blue-hoodie-with-hoodie-it_1230457-42660.jpg', name: 'Michael', budget: 3000, spent: 1500 },
23-
{ id: '4', image:'https://img.freepik.com/premium-vector/boy-with-hoodie-that-says-hes-boy_1230457-43316.jpg', name: 'Malow', budget: 1800, spent: 1200 },
24-
];
11+
const recipients: Recipient[] = [
12+
{ id: '1', image: 'https://img.freepik.com/premium-vector/cute-boy-smiling-cartoon-kawaii-boy-illustration-boy-avatar-happy-kid_1001605-3445.jpg', name: 'Alex', budget: 2000, spent: 1500 },
13+
{ id: '2', image: 'https://static.vecteezy.com/system/resources/previews/004/899/833/non_2x/beautiful-girl-with-blue-hair-avatar-of-woman-for-social-network-vector.jpg', name: 'Emily', budget: 2200, spent: 1600 },
14+
{ id: '3', image: 'https://img.freepik.com/premium-vector/boy-with-blue-hoodie-blue-hoodie-with-hoodie-it_1230457-42660.jpg', name: 'Michael', budget: 3000, spent: 1500 },
15+
{ id: '4', image: 'https://img.freepik.com/premium-vector/boy-with-hoodie-that-says-hes-boy_1230457-43316.jpg', name: 'Malow', budget: 1800, spent: 1200 },
16+
];
2517

26-
const handleAddRecipient = () => {
27-
router.push('/recipients/add-recipient');
28-
};
18+
const handleAddRecipient = () => {
19+
router.push('/recipients/add-recipient');
20+
};
2921

30-
return (
31-
<SafeAreaView style={styles.container}>
32-
<View style={styles.header}>
33-
<View style={styles.searchContainer}>
34-
<Ionicons
35-
name="search"
36-
size={20}
37-
color="#666"
38-
style={styles.searchIcon}
39-
/>
40-
<TextInput
41-
style={styles.searchInput}
42-
placeholder="Search"
43-
placeholderTextColor="#666"
44-
/>
45-
</View>
46-
<Pressable style={styles.addButton} onPress={handleAddRecipient}>
47-
<Text style={styles.addButtonText}>Add</Text>
48-
</Pressable>
49-
</View>
22+
return (
23+
<SafeAreaView style={styles.container}>
24+
<View style={styles.header}>
25+
<View style={styles.searchContainer}>
26+
<Ionicons
27+
name="search"
28+
size={20}
29+
color="#666"
30+
style={styles.searchIcon}
31+
/>
32+
<TextInput
33+
style={styles.searchInput}
34+
placeholder="Search"
35+
placeholderTextColor="#666"
36+
/>
37+
</View>
38+
<Pressable style={styles.addButton} onPress={handleAddRecipient}>
39+
<Text style={styles.addButtonText}>Add</Text>
40+
</Pressable>
41+
</View>
5042

51-
<Text style={styles.title}>All Recipients</Text>
43+
<Text style={styles.title}>All Recipients</Text>
5244

53-
<ScrollView style={styles.scrollView}>
54-
{recipients.map((recipient) => (
55-
<Pressable key={recipient.id} style={styles.recipientCard}>
56-
<Image
57-
source={{ uri: recipient.image }}
58-
style={styles.recipientImage}
59-
/>
60-
<View style={styles.recipientContent}>
61-
<Text style={styles.recipientName}>{recipient.name}</Text>
62-
<Text style={styles.budgetText}>Budget: ${recipient.budget}</Text>
63-
<Text style={styles.spentText}>Spent: ${recipient.spent}</Text>
64-
</View>
65-
</Pressable>
66-
))}
67-
</ScrollView>
68-
</SafeAreaView>
69-
);
45+
<ScrollView style={styles.scrollView}>
46+
{recipients.map((recipient) => (
47+
<RecipientCard
48+
key={recipient.id}
49+
id={recipient.id}
50+
image={recipient.image}
51+
name={recipient.name}
52+
description={recipient?.description}
53+
budget={recipient.budget}
54+
spent={recipient.spent}
55+
/>
56+
))}
57+
</ScrollView>
58+
</SafeAreaView>
59+
);
7060
};
7161

7262
const styles = StyleSheet.create({
73-
container: {
74-
flex: 1,
75-
backgroundColor: '#F8F9FA',
76-
},
77-
header: {
78-
flexDirection: 'row',
79-
alignItems: 'center',
80-
padding: 16,
81-
gap: 12,
82-
},
83-
searchContainer: {
84-
flex: 1,
85-
flexDirection: 'row',
86-
alignItems: 'center',
87-
backgroundColor: 'white',
88-
borderRadius: 8,
89-
paddingHorizontal: 12,
90-
},
91-
searchIcon: {
92-
marginRight: 8,
93-
},
94-
searchInput: {
95-
flex: 1,
96-
height: 40,
97-
fontSize: 16,
98-
color: '#333333',
99-
},
100-
addButton: {
101-
backgroundColor: '#4ADE80',
102-
paddingHorizontal: 20,
103-
paddingVertical: 10,
104-
borderRadius: 8,
105-
},
106-
addButtonText: {
107-
color: 'white',
108-
fontWeight: '600',
109-
},
110-
title: {
111-
fontSize: 24,
112-
fontWeight: '600',
113-
paddingHorizontal: 16,
114-
marginBottom: 16,
115-
color: '#33333',
116-
},
117-
scrollView: {
118-
flex: 1,
119-
},
120-
recipientCard: {
121-
backgroundColor: 'white',
122-
marginHorizontal: 16,
123-
marginBottom: 12,
124-
padding: 16,
125-
borderRadius: 12,
126-
shadowColor: '#000000',
127-
shadowOffset: { width: 0, height: 2 },
128-
shadowOpacity: 0.1,
129-
shadowRadius: 4,
130-
elevation: 2,
131-
flexDirection: 'row',
132-
alignItems: 'center',
133-
},
134-
recipientImage: {
135-
width: 60,
136-
height: 60,
137-
borderRadius: 8,
138-
},
139-
recipientContent: {
140-
marginLeft: 12,
141-
flex: 1,
142-
},
143-
recipientName: {
144-
fontSize: 18,
145-
fontWeight: '600',
146-
color: '#333333',
147-
},
148-
budgetText: {
149-
fontSize: 14,
150-
color: '#666666',
151-
marginBottom: 4,
152-
},
153-
spentText: {
154-
fontSize: 14,
155-
color: '#666666',
156-
},
63+
container: {
64+
flex: 1,
65+
backgroundColor: '#F8F9FA',
66+
},
67+
header: {
68+
flexDirection: 'row',
69+
alignItems: 'center',
70+
padding: 16,
71+
gap: 12,
72+
},
73+
searchContainer: {
74+
flex: 1,
75+
flexDirection: 'row',
76+
alignItems: 'center',
77+
backgroundColor: 'white',
78+
borderRadius: 8,
79+
paddingHorizontal: 12,
80+
},
81+
searchIcon: {
82+
marginRight: 8,
83+
},
84+
searchInput: {
85+
flex: 1,
86+
height: 40,
87+
fontSize: 16,
88+
color: '#333333',
89+
},
90+
addButton: {
91+
backgroundColor: '#4ADE80',
92+
paddingHorizontal: 20,
93+
paddingVertical: 10,
94+
borderRadius: 8,
95+
},
96+
addButtonText: {
97+
color: 'white',
98+
fontWeight: '600',
99+
},
100+
title: {
101+
fontSize: 24,
102+
fontWeight: '600',
103+
paddingHorizontal: 16,
104+
marginBottom: 16,
105+
color: '#33333',
106+
},
107+
scrollView: {
108+
flex: 1,
109+
},
157110
});
158111

159112
export default AllRecipientsScreen;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { useRouter } from 'expo-router';
2+
import { Image, Pressable, StyleSheet, Text, View } from 'react-native';
3+
import { Recipient } from '@/models/Recipient';
4+
5+
export default function RecipientCard({
6+
id,
7+
image,
8+
name,
9+
description,
10+
budget,
11+
spent,
12+
}: Recipient) {
13+
const router = useRouter();
14+
15+
const handlePress = () => {
16+
router.push({
17+
pathname: './recipients/detail-recipient',
18+
params: { id, image, name, description, budget, spent },
19+
});
20+
};
21+
22+
return (
23+
<Pressable style={styles.card} onPress={handlePress}>
24+
<Image source={{ uri: image }} style={styles.image} />
25+
<View style={styles.content}>
26+
<Text style={styles.name}>{name}</Text>
27+
{description && <Text style={styles.description}>{description}</Text>}
28+
<Text style={styles.budget}>Budget: ${budget}</Text>
29+
<Text style={styles.spent}>Spent: ${spent}</Text>
30+
</View>
31+
</Pressable>
32+
);
33+
}
34+
35+
const styles = StyleSheet.create({
36+
card: {
37+
backgroundColor: 'white',
38+
borderRadius: 12,
39+
marginHorizontal: 16,
40+
marginVertical: 8,
41+
flexDirection: 'row',
42+
padding: 12,
43+
shadowColor: '#000000',
44+
shadowOffset: { width: 0, height: 2 },
45+
shadowOpacity: 0.1,
46+
shadowRadius: 4,
47+
elevation: 2,
48+
alignItems: 'center',
49+
},
50+
image: {
51+
width: 60,
52+
height: 60,
53+
borderRadius: 8,
54+
},
55+
content: {
56+
marginLeft: 12,
57+
flex: 1,
58+
},
59+
name: {
60+
fontSize: 16,
61+
fontWeight: '600',
62+
color: '#333333',
63+
},
64+
description: {
65+
fontSize: 14,
66+
color: '#666666',
67+
marginTop: 4,
68+
},
69+
budget: {
70+
fontSize: 14,
71+
color: '#666666',
72+
marginTop: 4,
73+
},
74+
spent: {
75+
fontSize: 14,
76+
color: '#666666',
77+
marginTop: 4,
78+
},
79+
actions: {
80+
flexDirection: 'column',
81+
alignItems: 'center',
82+
justifyContent: 'space-evenly',
83+
},
84+
actionButton: {
85+
marginVertical: 8,
86+
},
87+
});

0 commit comments

Comments
 (0)