index.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import React, { FC, useEffect, useState } from 'react';
  2. import { Text, TouchableOpacity, View, Image, StyleSheet } from 'react-native';
  3. import { NavigationProp, useFocusEffect } from '@react-navigation/native';
  4. import { storage, StoreType } from 'src/storage';
  5. import { PageWrapper, Header, Input, AvatarWithInitials, WarningModal } from 'src/components';
  6. import { usePostGetGroupMembersQuery, usePostGetGroupSettingsQuery } from '@api/chat';
  7. import { Colors } from 'src/theme';
  8. import { API_HOST } from 'src/constants';
  9. import { getFontSize } from 'src/utils';
  10. import { SheetManager } from 'react-native-actions-sheet';
  11. import UserOptionsModal from '../Components/UserOptionsModal';
  12. import { chatStyles } from '../Components/styles';
  13. import { FlashList } from '@shopify/flash-list';
  14. import SearchIcon from 'assets/icons/search.svg';
  15. import DotsIcon from 'assets/icons/messages/dots-vertical.svg';
  16. type Props = {
  17. navigation: NavigationProp<any>;
  18. route: any;
  19. };
  20. const MembersListScreen: FC<Props> = ({ navigation, route }) => {
  21. const token = storage.get('token', StoreType.STRING) as string;
  22. const currentUserId = storage.get('uid', StoreType.STRING) as string;
  23. const { groupToken, canChangeAdmin } = route.params;
  24. const [modalState, setModalState] = useState({
  25. isWarningVisible: false,
  26. title: '',
  27. buttonTitle: '',
  28. message: '',
  29. action: () => {}
  30. });
  31. const [searchQuery, setSearchQuery] = useState('');
  32. const [filteredData, setFilteredData] = useState<any[]>([]);
  33. const { data, refetch } = usePostGetGroupSettingsQuery(token, groupToken, true);
  34. const { data: members, refetch: refetchMembers } = usePostGetGroupMembersQuery(
  35. token,
  36. groupToken,
  37. true
  38. );
  39. useFocusEffect(() => {
  40. navigation.getParent()?.setOptions({
  41. tabBarStyle: {
  42. display: 'none'
  43. }
  44. });
  45. });
  46. useEffect(() => {
  47. if (members && members.settings) {
  48. setFilteredData(members.settings);
  49. }
  50. }, [members]);
  51. const handleSearch = (text: string) => {
  52. if (text && members) {
  53. const searchData =
  54. members?.settings?.filter((item: any) => {
  55. const itemData = item.name ? item.name.toLowerCase() : ''.toLowerCase();
  56. const textData = text.toLowerCase();
  57. return itemData.indexOf(textData) > -1;
  58. }) ?? [];
  59. setFilteredData(searchData);
  60. setSearchQuery(text);
  61. } else {
  62. setFilteredData(members?.settings ?? []);
  63. setSearchQuery(text);
  64. }
  65. };
  66. const renderItem = ({ item }: { item: any }) => (
  67. <View style={styles.userItem}>
  68. {item.avatar ? (
  69. <Image source={{ uri: API_HOST + item.avatar }} style={chatStyles.avatar} />
  70. ) : (
  71. <AvatarWithInitials
  72. text={item.name?.split(' ')[0][0] + item.name?.split(' ')[1][0]}
  73. flag={API_HOST + item?.flag1}
  74. size={36}
  75. fontSize={12}
  76. borderColor={Colors.LIGHT_GRAY}
  77. borderWidth={1}
  78. />
  79. )}
  80. <View style={chatStyles.textContainer}>
  81. <Text style={chatStyles.name}>{item.name}</Text>
  82. </View>
  83. {item.admin === 1 && (
  84. <Text
  85. style={{
  86. fontSize: getFontSize(10),
  87. fontWeight: '600',
  88. color: Colors.LIGHT_GRAY
  89. }}
  90. >
  91. Admin
  92. </Text>
  93. )}
  94. {item.uid !== +currentUserId && (
  95. <TouchableOpacity
  96. style={{ padding: 6 }}
  97. onPress={() =>
  98. SheetManager.show('user-options-modal', {
  99. payload: {
  100. admin: item.admin,
  101. uid: item.uid,
  102. name: item.name,
  103. canChangeAdmin,
  104. token,
  105. groupToken,
  106. refetch,
  107. refetchMembers,
  108. setIsWarningVisible: setModalState
  109. } as any
  110. })
  111. }
  112. >
  113. <DotsIcon />
  114. </TouchableOpacity>
  115. )}
  116. </View>
  117. );
  118. return (
  119. <PageWrapper>
  120. <Header label="Nomads" />
  121. <View style={styles.container}>
  122. <Input
  123. inputMode={'search'}
  124. placeholder={'Search nomads'}
  125. onChange={handleSearch}
  126. value={searchQuery}
  127. icon={<SearchIcon fill={'#C8C8C8'} width={14} height={14} />}
  128. />
  129. <FlashList
  130. viewabilityConfig={{
  131. waitForInteraction: true,
  132. itemVisiblePercentThreshold: 50,
  133. minimumViewTime: 1000
  134. }}
  135. data={filteredData || []}
  136. renderItem={renderItem}
  137. keyExtractor={(item) => item.uid.toString()}
  138. estimatedItemSize={100}
  139. extraData={filteredData}
  140. showsVerticalScrollIndicator={false}
  141. contentContainerStyle={{ paddingBottom: 16 }}
  142. />
  143. </View>
  144. <WarningModal
  145. type={'delete'}
  146. isVisible={modalState.isWarningVisible}
  147. buttonTitle={modalState.buttonTitle}
  148. message={modalState.message}
  149. action={modalState.action}
  150. onClose={() => setModalState({ ...modalState, isWarningVisible: false })}
  151. title={modalState.title}
  152. />
  153. <UserOptionsModal />
  154. </PageWrapper>
  155. );
  156. };
  157. const styles = StyleSheet.create({
  158. container: {
  159. backgroundColor: 'white',
  160. gap: 16,
  161. flex: 1
  162. },
  163. avatar: {
  164. width: 30,
  165. height: 30,
  166. borderRadius: 15,
  167. borderWidth: 1,
  168. borderColor: Colors.LIGHT_GRAY
  169. },
  170. header: {
  171. paddingTop: 16,
  172. paddingHorizontal: 6,
  173. width: 68
  174. },
  175. userItem: {
  176. flexDirection: 'row',
  177. alignItems: 'center',
  178. paddingVertical: 8,
  179. paddingHorizontal: 12,
  180. backgroundColor: Colors.FILL_LIGHT,
  181. gap: 8,
  182. borderRadius: 8,
  183. marginBottom: 6
  184. }
  185. });
  186. export default MembersListScreen;