index.tsx 5.8 KB

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