SeriesModal.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import React, { useState } from 'react';
  2. import { View, Text, Image, StyleSheet, TouchableOpacity, Platform } from 'react-native';
  3. import { FlashList } from '@shopify/flash-list';
  4. import ActionSheet, { SheetManager } from 'react-native-actions-sheet';
  5. import { Colors } from 'src/theme';
  6. import { API_HOST } from 'src/constants';
  7. import { getFontSize } from 'src/utils';
  8. import { useSafeAreaInsets } from 'react-native-safe-area-context';
  9. import { Loading } from 'src/components';
  10. import { usePostGetProfileSeriesData } from '@api/user';
  11. import { storage, StoreType } from 'src/storage';
  12. import CheckSvg from 'assets/icons/travels-screens/circle-check.svg';
  13. import CloseSVG from 'assets/icons/close.svg';
  14. const SeriesModal = () => {
  15. const token = storage.get('token', StoreType.STRING) as string;
  16. const insets = useSafeAreaInsets();
  17. const [userId, setUserId] = useState<number | null>(null);
  18. const [seriesId, setSeriesId] = useState<number | null>(null);
  19. const { data: seriesData } = usePostGetProfileSeriesData(
  20. token,
  21. userId ?? 0,
  22. seriesId ?? 0,
  23. seriesId && userId ? true : false
  24. );
  25. const handleSheetOpen = (payload: any) => {
  26. setSeriesId(payload?.seriesId);
  27. setUserId(payload?.userId);
  28. };
  29. const renderCountryItem = ({ item: country }: { item: any }) => {
  30. const visibleItems = country.items;
  31. return (
  32. <View style={styles.countryContainer}>
  33. {country.icon || country.name ? (
  34. <>
  35. <View style={styles.countryHeader}>
  36. {country.icon ? (
  37. <Image source={{ uri: `${API_HOST}${country.icon}` }} style={styles.flagIcon} />
  38. ) : null}
  39. {country.name ? <Text style={styles.countryName}>{country.name}</Text> : null}
  40. </View>
  41. <View style={styles.divider}></View>
  42. </>
  43. ) : null}
  44. <View style={styles.sitesContainer}>
  45. {visibleItems.map((site: { item_id: number; name: string }, index: number) => (
  46. <View key={index} style={styles.siteItem}>
  47. <View style={styles.checkIcon}>
  48. <CheckSvg width={16} height={16} fill={Colors.DARK_BLUE} />
  49. </View>
  50. <Text style={styles.siteName}>{site.name}</Text>
  51. </View>
  52. ))}
  53. </View>
  54. </View>
  55. );
  56. };
  57. const renderHeader = () => (
  58. <View style={styles.headerContainer}>
  59. <Image source={{ uri: `${API_HOST}${seriesData?.series_icon}` }} style={styles.seriesIcon} />
  60. <Text style={styles.seriesTitle}>{seriesData?.series_name}</Text>
  61. </View>
  62. );
  63. return (
  64. <ActionSheet
  65. id="visited-series-modal"
  66. gestureEnabled={Platform.OS === 'ios'}
  67. onBeforeShow={(sheetRef) => {
  68. const payload = sheetRef || null;
  69. handleSheetOpen(payload);
  70. }}
  71. containerStyle={styles.sheetContainer}
  72. defaultOverlayOpacity={0.5}
  73. >
  74. {Platform.OS === 'android' && (
  75. <TouchableOpacity
  76. onPress={() => SheetManager.hide('visited-series-modal')}
  77. style={{ marginLeft: 14, padding: 4 }}
  78. hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
  79. >
  80. <CloseSVG />
  81. </TouchableOpacity>
  82. )}
  83. {seriesData ? (
  84. <View style={[styles.container, { paddingBottom: insets.bottom }]}>
  85. {renderHeader()}
  86. <View style={styles.listContainer}>
  87. <FlashList
  88. keyExtractor={(item, index) => item.name + index.toString()}
  89. data={seriesData.items_grouped}
  90. renderItem={renderCountryItem}
  91. estimatedItemSize={200}
  92. showsVerticalScrollIndicator={false}
  93. ItemSeparatorComponent={() => <View style={styles.separator} />}
  94. />
  95. </View>
  96. </View>
  97. ) : (
  98. <View style={[styles.container, { paddingBottom: insets.bottom, paddingTop: 0 }]}>
  99. <Loading />
  100. </View>
  101. )}
  102. </ActionSheet>
  103. );
  104. };
  105. const styles = StyleSheet.create({
  106. sheetContainer: {
  107. borderTopLeftRadius: 15,
  108. borderTopRightRadius: 15,
  109. height: '92%'
  110. },
  111. container: {
  112. backgroundColor: 'white',
  113. paddingHorizontal: 16,
  114. paddingTop: 8,
  115. height: '100%'
  116. },
  117. listContainer: {
  118. flex: 1,
  119. minHeight: 300
  120. },
  121. headerContainer: {
  122. alignItems: 'center',
  123. paddingBottom: 12,
  124. gap: 8
  125. },
  126. seriesIcon: {
  127. width: 32,
  128. height: 32
  129. },
  130. seriesTitle: {
  131. fontSize: getFontSize(14),
  132. fontFamily: 'montserrat-700',
  133. color: Colors.DARK_BLUE,
  134. textAlign: 'center'
  135. },
  136. countryContainer: {
  137. backgroundColor: Colors.FILL_LIGHT,
  138. borderRadius: 8,
  139. padding: 12,
  140. gap: 8
  141. },
  142. countryHeader: {
  143. flexDirection: 'row',
  144. alignItems: 'center',
  145. gap: 8
  146. },
  147. flagIcon: {
  148. width: 24,
  149. height: 24,
  150. borderRadius: 12,
  151. borderWidth: 0.5,
  152. borderColor: Colors.BORDER_LIGHT
  153. },
  154. countryName: {
  155. fontSize: getFontSize(14),
  156. fontFamily: 'montserrat-700',
  157. color: Colors.DARK_BLUE
  158. },
  159. divider: {
  160. height: 1,
  161. backgroundColor: '#D3D3D3'
  162. },
  163. sitesContainer: {
  164. gap: 8
  165. },
  166. siteItem: {
  167. flexDirection: 'row',
  168. alignItems: 'center',
  169. justifyContent: 'center',
  170. gap: 8
  171. },
  172. checkIcon: {
  173. width: 24,
  174. height: 24,
  175. justifyContent: 'center',
  176. alignItems: 'center'
  177. },
  178. siteName: {
  179. fontSize: getFontSize(12),
  180. color: Colors.DARK_BLUE,
  181. fontWeight: '600',
  182. flex: 1
  183. },
  184. separator: {
  185. height: 8
  186. }
  187. });
  188. export default SeriesModal;