1- import { StyleSheet , Text , TouchableOpacity , View } from 'react-native' ;
1+ import { MaterialIcons } from '@expo/vector-icons' ;
2+ import React , { useState } from 'react' ;
3+ import {
4+ FlatList ,
5+ Modal ,
6+ StyleSheet ,
7+ Text ,
8+ TouchableOpacity ,
9+ TouchableWithoutFeedback ,
10+ View ,
11+ } from 'react-native' ;
212
313interface FilterTabsProps {
414 selectedTab : string ;
515 onSelectTab : ( tab : string ) => void ;
16+ recipients : { id : string ; name : string } [ ] ;
17+ selectedRecipient : string | null ;
18+ onSelectRecipient : ( recipientId : string | null ) => void ;
619}
720
821export default function FilterTabs ( {
922 selectedTab,
1023 onSelectTab,
24+ recipients,
25+ selectedRecipient,
26+ onSelectRecipient,
1127} : FilterTabsProps ) {
12- const tabs = [ 'All' , 'Recipient' , 'Occasion' , 'Tag' ] ;
28+ const tabs = [ 'All' , 'Recipients' ] ;
29+ const [ showRecipientModal , setShowRecipientModal ] = useState ( false ) ;
30+
31+ const selectedRecipientName =
32+ recipients . find ( ( r ) => r . id === selectedRecipient ) ?. name || 'Recipients' ;
1333
1434 return (
1535 < View style = { styles . container } >
1636 { tabs . map ( ( tab ) => (
1737 < TouchableOpacity
1838 key = { tab }
19- style = { [ styles . tab , selectedTab === tab && styles . selectedTab ] }
20- onPress = { ( ) => onSelectTab ( tab ) }
39+ style = { [
40+ styles . tab ,
41+ tab === 'All' && styles . selectedTab ,
42+ tab === 'Recipients' &&
43+ selectedRecipient &&
44+ styles . activeRecipientTab ,
45+ ] }
46+ onPress = { ( ) => {
47+ if ( tab === 'Recipients' ) {
48+ setShowRecipientModal ( true ) ;
49+ }
50+ } }
2151 >
2252 < Text
23- style = { [
24- styles . tabText ,
25- selectedTab === tab && styles . selectedTabText ,
26- ] }
53+ style = { [ styles . tabText , tab === 'All' && styles . selectedTabText ] }
2754 >
28- { tab }
55+ { tab === 'Recipients' ? selectedRecipientName : tab }
2956 </ Text >
57+ { tab === 'Recipients' && (
58+ < MaterialIcons
59+ name = "filter-list"
60+ size = { 16 }
61+ color = { selectedRecipient ? '#4B6BFB' : '#666' }
62+ style = { styles . filterIcon }
63+ />
64+ ) }
3065 </ TouchableOpacity >
3166 ) ) }
67+
68+ { /* Dialog chọn recipient */ }
69+ < Modal
70+ visible = { showRecipientModal }
71+ transparent = { true }
72+ animationType = "slide"
73+ onRequestClose = { ( ) => setShowRecipientModal ( false ) }
74+ >
75+ < TouchableWithoutFeedback onPress = { ( ) => setShowRecipientModal ( false ) } >
76+ < View style = { styles . modalOverlay } >
77+ < TouchableWithoutFeedback >
78+ < View style = { styles . modalContent } >
79+ < Text style = { styles . modalTitle } > Select Recipient</ Text >
80+ < FlatList
81+ data = { recipients }
82+ keyExtractor = { ( item ) => item . id }
83+ renderItem = { ( { item } ) => (
84+ < TouchableOpacity
85+ style = { [
86+ styles . option ,
87+ item . id === selectedRecipient && styles . activeOption ,
88+ ] }
89+ onPress = { ( ) => {
90+ onSelectRecipient ( item . id ) ;
91+ setShowRecipientModal ( false ) ;
92+ } }
93+ >
94+ < Text
95+ style = { [
96+ styles . optionText ,
97+ item . id === selectedRecipient &&
98+ styles . activeOptionText ,
99+ ] }
100+ >
101+ { item . name }
102+ </ Text >
103+ </ TouchableOpacity >
104+ ) }
105+ />
106+ < TouchableOpacity
107+ style = { styles . option }
108+ onPress = { ( ) => {
109+ onSelectRecipient ( null ) ;
110+ setShowRecipientModal ( false ) ;
111+ } }
112+ >
113+ < Text style = { styles . optionText } > Clear Selection</ Text >
114+ </ TouchableOpacity >
115+ </ View >
116+ </ TouchableWithoutFeedback >
117+ </ View >
118+ </ TouchableWithoutFeedback >
119+ </ Modal >
32120 </ View >
33121 ) ;
34122}
@@ -41,6 +129,8 @@ const styles = StyleSheet.create({
41129 gap : 8 ,
42130 } ,
43131 tab : {
132+ flexDirection : 'row' ,
133+ alignItems : 'center' ,
44134 paddingHorizontal : 16 ,
45135 paddingVertical : 8 ,
46136 borderRadius : 20 ,
@@ -49,11 +139,52 @@ const styles = StyleSheet.create({
49139 selectedTab : {
50140 backgroundColor : '#e8eeff' ,
51141 } ,
142+ activeRecipientTab : {
143+ borderColor : '#4B6BFB' ,
144+ borderWidth : 1 ,
145+ } ,
52146 tabText : {
53147 color : '#666' ,
54148 fontSize : 14 ,
55149 } ,
56150 selectedTabText : {
57151 color : '#4B6BFB' ,
58152 } ,
153+ filterIcon : {
154+ marginLeft : 4 ,
155+ } ,
156+ modalOverlay : {
157+ flex : 1 ,
158+ backgroundColor : 'rgba(0, 0, 0, 0.5)' ,
159+ justifyContent : 'center' ,
160+ alignItems : 'center' ,
161+ } ,
162+ modalContent : {
163+ width : '80%' ,
164+ backgroundColor : 'white' ,
165+ borderRadius : 8 ,
166+ padding : 16 ,
167+ } ,
168+ modalTitle : {
169+ fontSize : 18 ,
170+ fontWeight : 'bold' ,
171+ marginBottom : 16 ,
172+ textAlign : 'center' ,
173+ } ,
174+ option : {
175+ paddingVertical : 12 ,
176+ borderBottomWidth : 1 ,
177+ borderBottomColor : '#E0E0E0' ,
178+ } ,
179+ activeOption : {
180+ backgroundColor : '#e8eeff' ,
181+ } ,
182+ optionText : {
183+ fontSize : 16 ,
184+ color : '#333' ,
185+ textAlign : 'center' ,
186+ } ,
187+ activeOptionText : {
188+ color : '#4B6BFB' ,
189+ } ,
59190} ) ;
0 commit comments