index.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import React, { useState } from 'react';
  2. import { View, Text, TouchableOpacity, Image } from 'react-native';
  3. import { TabView, TabBar } from 'react-native-tab-view';
  4. import ReactModal from 'react-native-modal';
  5. import { FlashList } from '@shopify/flash-list';
  6. import { useNavigation } from '@react-navigation/native';
  7. import { Colors } from 'src/theme';
  8. import { styles } from './styles';
  9. import { NAVIGATION_PAGES } from 'src/types';
  10. import { API_HOST } from 'src/constants';
  11. import { Loading, WarningModal } from 'src/components';
  12. import { StoreType, storage } from 'src/storage';
  13. const SearchModal = ({
  14. searchVisible,
  15. handleCloseModal,
  16. handleFindRegion,
  17. index,
  18. searchData,
  19. setIndex,
  20. token
  21. }: {
  22. searchVisible: boolean;
  23. handleCloseModal: () => void;
  24. handleFindRegion: (id: number, type: 'regions' | 'countries' | 'places') => void;
  25. index: number;
  26. searchData: any;
  27. setIndex: (index: number) => void;
  28. token: string | undefined;
  29. }) => {
  30. const navigation = useNavigation();
  31. const [routes] = useState([
  32. { key: 'users', title: 'Nomads' },
  33. { key: 'regions', title: 'NM regions' },
  34. { key: 'dare', title: 'DARE places' }
  35. ]);
  36. const [shouldOpenModal, setShouldOpenModal] = useState<{
  37. id: number;
  38. type: 'regions' | 'countries' | 'places';
  39. } | null>(null);
  40. const [warningVisible, setWarningVisible] = useState(false);
  41. const renderItem = ({ item }: { item: any }) => {
  42. const [name, ...rest] = item.name?.split(/ – | - /);
  43. const subname = rest?.join(' - ');
  44. return index === 0 ? (
  45. <TouchableOpacity
  46. style={{ paddingVertical: 12 }}
  47. onPress={() => {
  48. if (!token) {
  49. setWarningVisible(true);
  50. } else {
  51. handleCloseModal();
  52. navigation.navigate(
  53. ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.id }] as never)
  54. );
  55. }
  56. }}
  57. >
  58. <View style={styles.container}>
  59. <Image
  60. source={
  61. item.avatar
  62. ? { uri: API_HOST + item.avatar }
  63. : require('../../../../../assets/logo-ua.png')
  64. }
  65. style={styles.img}
  66. />
  67. <View style={styles.textContainer}>
  68. <Text style={styles.title}>{item.name}</Text>
  69. <View style={{ flexDirection: 'row', alignItems: 'center' }}>
  70. <Image source={{ uri: API_HOST + item.flag1 }} style={styles.flagSmall} />
  71. {item.flag2 && item.flag2 !== item.flag1 && (
  72. <Image
  73. source={{ uri: API_HOST + item.flag2 }}
  74. style={[
  75. styles.flagSmall,
  76. {
  77. marginLeft: -6
  78. }
  79. ]}
  80. />
  81. )}
  82. </View>
  83. </View>
  84. </View>
  85. </TouchableOpacity>
  86. ) : (
  87. <TouchableOpacity
  88. style={{ paddingVertical: 12 }}
  89. onPress={() => {
  90. handleCloseModal();
  91. if (index === 1) {
  92. setShouldOpenModal({ id: item.id, type: 'regions' });
  93. } else {
  94. setShouldOpenModal({ id: item.id, type: 'places' });
  95. }
  96. }}
  97. >
  98. <View style={styles.container}>
  99. {item.flag1 && <Image source={{ uri: API_HOST + item.flag1 }} style={styles.img} />}
  100. {item.flag2 && (
  101. <Image
  102. source={{ uri: API_HOST + item.flag2 }}
  103. style={[
  104. styles.img,
  105. {
  106. marginLeft: -20
  107. }
  108. ]}
  109. />
  110. )}
  111. <View style={styles.textContainer}>
  112. <Text style={styles.title}>{name}</Text>
  113. <Text style={styles.subTitle}>{subname}</Text>
  114. </View>
  115. </View>
  116. </TouchableOpacity>
  117. );
  118. };
  119. const renderScene = ({ route }: { route: any }) => {
  120. return (
  121. <View style={{ flex: 1 }}>
  122. {searchData?.[route.key] ? (
  123. <FlashList
  124. viewabilityConfig={{
  125. waitForInteraction: true,
  126. itemVisiblePercentThreshold: 50,
  127. minimumViewTime: 1000
  128. }}
  129. estimatedItemSize={45}
  130. data={searchData?.[route.key]}
  131. renderItem={renderItem}
  132. keyExtractor={(item) => item.id.toString()}
  133. showsVerticalScrollIndicator={false}
  134. contentContainerStyle={{ paddingVertical: 16, paddingHorizontal: 8 }}
  135. />
  136. ) : (
  137. <Loading />
  138. )}
  139. <WarningModal
  140. type="unauthorized"
  141. isVisible={warningVisible}
  142. onClose={() => setWarningVisible(false)}
  143. action={handleCloseModal}
  144. />
  145. </View>
  146. );
  147. };
  148. return (
  149. <ReactModal
  150. isVisible={searchVisible}
  151. onBackdropPress={handleCloseModal}
  152. onBackButtonPress={handleCloseModal}
  153. style={styles.modal}
  154. statusBarTranslucent={true}
  155. presentationStyle="overFullScreen"
  156. onModalHide={() => {
  157. if (shouldOpenModal) {
  158. handleFindRegion(shouldOpenModal.id, shouldOpenModal.type);
  159. setShouldOpenModal(null);
  160. }
  161. }}
  162. >
  163. <View style={styles.modalContainer}>
  164. <TabView
  165. navigationState={{ index, routes }}
  166. renderScene={renderScene}
  167. onIndexChange={setIndex}
  168. lazy={true}
  169. renderTabBar={(props) => (
  170. <TabBar
  171. {...props}
  172. indicatorStyle={{ backgroundColor: Colors.DARK_BLUE }}
  173. style={styles.tabBar}
  174. tabStyle={styles.tabStyle}
  175. pressColor={'transparent'}
  176. renderLabel={({ route, focused }) => (
  177. <Text
  178. style={[styles.tabLabel, { color: Colors.DARK_BLUE, opacity: focused ? 1 : 0.4 }]}
  179. >
  180. {route.title}
  181. </Text>
  182. )}
  183. />
  184. )}
  185. />
  186. </View>
  187. </ReactModal>
  188. );
  189. };
  190. export default SearchModal;