RouteSearch.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import React, { useEffect, useState } from 'react';
  2. import { View, Text, Image, TouchableOpacity, StyleSheet, ActivityIndicator } from 'react-native';
  3. import { FlashList } from '@shopify/flash-list';
  4. import { storage, StoreType } from 'src/storage';
  5. import { usePostSearchUsers } from '@api/chat';
  6. import { API_HOST } from 'src/constants';
  7. import { Colors } from 'src/theme';
  8. import { useNavigation } from '@react-navigation/native';
  9. import { NAVIGATION_PAGES } from 'src/types';
  10. import { getFontSize } from 'src/utils';
  11. import { AvatarWithInitials, Input } from 'src/components';
  12. import SearchIcon from 'assets/icons/search.svg';
  13. import NomadsIcon from 'assets/icons/bottom-navigation/travellers.svg';
  14. import { SheetManager, useSheetRouter } from 'react-native-actions-sheet';
  15. const RouteSearch = () => {
  16. const router = useSheetRouter('search-modal');
  17. const navigation = useNavigation();
  18. const token = storage.get('token', StoreType.STRING) as string;
  19. const [searchQuery, setSearchQuery] = useState('');
  20. const { data: searchResult, isFetching } = usePostSearchUsers(
  21. token,
  22. searchQuery,
  23. searchQuery.length > 1
  24. );
  25. useEffect(() => {}, [searchResult]);
  26. const renderItem = ({ item }: { item: any }) => (
  27. <TouchableOpacity
  28. style={styles.itemContainer}
  29. onPress={() => {
  30. SheetManager.hide('search-modal').then(() => {
  31. navigation.navigate(
  32. ...([
  33. NAVIGATION_PAGES.CHAT,
  34. {
  35. id: item.user_id,
  36. name: item.first_name + ' ' + item.last_name,
  37. avatar: item.avatar,
  38. userType: 'normal'
  39. }
  40. ] as never)
  41. );
  42. });
  43. }}
  44. >
  45. {item.avatar ? (
  46. <Image source={{ uri: API_HOST + item.avatar }} style={styles.avatar} />
  47. ) : (
  48. <AvatarWithInitials
  49. text={`${item.first_name[0] ?? ''}${item.last_name[0] ?? ''}`}
  50. flag={API_HOST + item.homebase_flag}
  51. size={30}
  52. fontSize={12}
  53. />
  54. )}
  55. <View style={styles.textContainer}>
  56. <Text style={styles.name}>
  57. {item.first_name} {item.last_name}
  58. </Text>
  59. </View>
  60. </TouchableOpacity>
  61. );
  62. return (
  63. <View style={styles.container}>
  64. <TouchableOpacity style={styles.header} onPress={() => router?.goBack()}>
  65. <Text style={styles.cancelText}>Cancel</Text>
  66. </TouchableOpacity>
  67. <Input
  68. inputMode={'search'}
  69. placeholder={'Search nomads'}
  70. onChange={(text) => {
  71. setSearchQuery(text);
  72. }}
  73. value={searchQuery}
  74. icon={<SearchIcon fill={'#C8C8C8'} width={14} height={14} />}
  75. />
  76. <TouchableOpacity style={styles.newGroup} onPress={() => router?.navigate('route-add-users')}>
  77. <Text style={styles.text}>New group chat</Text>
  78. <NomadsIcon fill={Colors.DARK_BLUE} width={20} height={16} />
  79. </TouchableOpacity>
  80. {isFetching ? (
  81. <ActivityIndicator size="large" color={Colors.DARK_BLUE} />
  82. ) : (
  83. <View style={{ flex: 1 }}>
  84. <FlashList
  85. viewabilityConfig={{
  86. waitForInteraction: true,
  87. itemVisiblePercentThreshold: 50,
  88. minimumViewTime: 1000
  89. }}
  90. data={searchResult?.data || []}
  91. renderItem={renderItem}
  92. keyExtractor={(item) => item.user_id.toString()}
  93. estimatedItemSize={100}
  94. extraData={searchResult}
  95. showsVerticalScrollIndicator={false}
  96. refreshing={isFetching}
  97. contentContainerStyle={{ paddingBottom: 16 }}
  98. />
  99. </View>
  100. )}
  101. </View>
  102. );
  103. };
  104. const styles = StyleSheet.create({
  105. container: {
  106. backgroundColor: 'white',
  107. gap: 16,
  108. height: '100%'
  109. },
  110. header: {
  111. paddingTop: 16,
  112. paddingHorizontal: 6,
  113. width: 68
  114. },
  115. cancelText: {
  116. color: Colors.DARK_BLUE,
  117. fontSize: getFontSize(14),
  118. fontWeight: '700'
  119. },
  120. itemContainer: {
  121. flexDirection: 'row',
  122. alignItems: 'center',
  123. paddingBottom: 24,
  124. gap: 8
  125. },
  126. avatar: {
  127. width: 30,
  128. height: 30,
  129. borderRadius: 15,
  130. borderWidth: 1,
  131. borderColor: Colors.FILL_LIGHT
  132. },
  133. textContainer: {
  134. flex: 1
  135. },
  136. name: {
  137. fontSize: getFontSize(14),
  138. color: Colors.DARK_BLUE,
  139. fontFamily: 'montserrat-700'
  140. },
  141. newGroup: {
  142. flexDirection: 'row',
  143. justifyContent: 'space-between',
  144. alignItems: 'center',
  145. padding: 12,
  146. backgroundColor: Colors.FILL_LIGHT,
  147. borderRadius: 8,
  148. height: 44
  149. },
  150. text: {
  151. fontSize: getFontSize(12),
  152. color: Colors.DARK_BLUE,
  153. fontWeight: '700'
  154. }
  155. });
  156. export default RouteSearch;