index.tsx 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import React, { useCallback, useEffect, useState } from 'react';
  2. import { View, Text, TouchableOpacity, FlatList, Platform } from 'react-native';
  3. import * as Progress from 'react-native-progress';
  4. import { useFocusEffect, useNavigation } from '@react-navigation/native';
  5. import moment from 'moment';
  6. import { EditNmModal, Header, PageWrapper } from 'src/components';
  7. import { CustomButton } from '../Components';
  8. import { NmRegionItem } from '../Components/MyRegionsItems/NmRegionItem';
  9. import { RegionItem } from '../Components/MyRegionsItems/RegionItem';
  10. import MegaregionsModal from '../Components/MegaregionsModal';
  11. import { StoreType, storage } from 'src/storage';
  12. import { NmRegion, TCCRegion } from '../utils/types';
  13. import { Colors } from 'src/theme';
  14. import { styles } from './styles';
  15. import {
  16. useGetMegaregionsQuery,
  17. useGetRegionQeQuery,
  18. usePostSetTCCRegionMutation
  19. } from '@api/myRegions';
  20. import { qualityOptions } from '../utils/constants';
  21. import ChevronIcon from 'assets/icons/travels-screens/down-arrow.svg';
  22. import { NAVIGATION_PAGES } from 'src/types';
  23. import { useRegion } from 'src/contexts/RegionContext';
  24. const RegionsScreen = () => {
  25. const token = storage.get('token', StoreType.STRING) as string;
  26. const { data: megaregions } = useGetMegaregionsQuery(String(token), true);
  27. const [megaSelectorVisible, setMegaSelectorVisible] = useState(false);
  28. const [selectedMega, setSelectedMega] = useState<{ name: string; id: number }>({
  29. id: 1,
  30. name: 'SOUTHERN EUROPE'
  31. });
  32. const { data: regionsQe } = useGetRegionQeQuery(selectedMega.id, String(token), true);
  33. const [total, setTotal] = useState(0);
  34. const [isEditModalVisible, setIsEditModalVisible] = useState(false);
  35. const [contentIndex, setContentIndex] = useState(0);
  36. const [filteredNmRegions, setFilteredNmRegions] = useState<NmRegion[] | null>(null);
  37. const [tccRegions, setTccRegions] = useState<TCCRegion[] | null>(null);
  38. const [filteredTccRegions, setFilteredTccRegions] = useState<TCCRegion[] | null>(null);
  39. const { mutate: updateTCC } = usePostSetTCCRegionMutation();
  40. const [modalState, setModalState] = useState({
  41. selectedFirstYear: 2021,
  42. selectedLastYear: 2021,
  43. selectedQuality: qualityOptions[2],
  44. selectedNoOfVisits: 1,
  45. years: [],
  46. id: null
  47. });
  48. const navigation = useNavigation();
  49. const { handleUpdateNMList: handleUpdateNM, nmRegions, setNmRegions, setUserData } = useRegion();
  50. useFocusEffect(
  51. useCallback(() => {
  52. navigation.getParent()?.setOptions({
  53. tabBarStyle: {
  54. display: 'flex',
  55. ...Platform.select({
  56. android: {
  57. height: 58
  58. }
  59. })
  60. }
  61. });
  62. }, [navigation])
  63. );
  64. useEffect(() => {
  65. const currentYear = moment().year();
  66. let yearSelector: { label: string; value: number }[] = [{ label: 'visited', value: 1 }];
  67. for (let i = currentYear; i >= 1951; i--) {
  68. yearSelector.push({ label: i.toString(), value: i });
  69. }
  70. handleModalStateChange({ years: yearSelector });
  71. }, []);
  72. const handleModalStateChange = (updates: { [key: string]: any }) => {
  73. setModalState((prevState) => ({ ...prevState, ...updates }));
  74. };
  75. const handleOpenEditModal = (item: NmRegion) => {
  76. handleModalStateChange({
  77. selectedFirstYear: item.year,
  78. selectedLastYear: item.last,
  79. selectedQuality:
  80. qualityOptions.find((quality) => quality.id === item.quality) || qualityOptions[2],
  81. selectedNoOfVisits: item.visits || 1,
  82. id: item.id
  83. });
  84. setIsEditModalVisible(true);
  85. };
  86. const handleUpdateTCC = useCallback(
  87. (region: number, visits: 0 | 1) => {
  88. const updatedTCC = tccRegions?.map((item) => {
  89. if (item.id === region) {
  90. return {
  91. ...item,
  92. visited: visits
  93. };
  94. }
  95. return item;
  96. });
  97. const updatedTCCData = {
  98. token,
  99. region,
  100. visits
  101. };
  102. updateTCC(updatedTCCData);
  103. updatedTCC && setTccRegions(updatedTCC);
  104. },
  105. [tccRegions]
  106. );
  107. useEffect(() => {
  108. if (nmRegions && nmRegions.length && token) {
  109. calcTotalCountries();
  110. }
  111. }, [nmRegions]);
  112. useEffect(() => {
  113. if (regionsQe && regionsQe.result === 'OK') {
  114. setNmRegions(regionsQe.data.out_regs);
  115. setTccRegions(regionsQe.data.out_tcc);
  116. }
  117. }, [regionsQe]);
  118. useEffect(() => {
  119. if (megaregions && megaregions.result === 'OK') {
  120. setContentIndex(0);
  121. }
  122. }, [selectedMega]);
  123. useEffect(() => {
  124. switch (contentIndex) {
  125. case 0:
  126. setFilteredNmRegions(nmRegions);
  127. setFilteredTccRegions(tccRegions);
  128. break;
  129. case 1:
  130. setFilteredNmRegions(nmRegions?.filter((item: NmRegion) => item.visits <= 0) || []);
  131. setFilteredTccRegions(tccRegions?.filter((item) => item.visited <= 0) || []);
  132. break;
  133. case 2:
  134. setFilteredNmRegions(nmRegions?.filter((item: NmRegion) => item.visits > 0) || []);
  135. setFilteredTccRegions(tccRegions?.filter((item) => item.visited > 0) || []);
  136. break;
  137. }
  138. }, [contentIndex, nmRegions, tccRegions]);
  139. useFocusEffect(
  140. useCallback(() => {
  141. if (megaregions && megaregions.result === 'OK') {
  142. setSelectedMega(megaregions.data[1]);
  143. }
  144. }, [megaregions])
  145. );
  146. const calcTotalCountries = () => {
  147. const visited = nmRegions?.filter((item: NmRegion) => item.visits > 0).length || 0;
  148. setTotal(visited);
  149. };
  150. const renderItem = ({ item }: { item: NmRegion }) => (
  151. <TouchableOpacity onPress={() => {
  152. setUserData({
  153. type: 'nm',
  154. region_flag: item.flag_1,
  155. region_name: item.region_name,
  156. best_visit_quality: item.quality,
  157. first_visit_year: item.year,
  158. last_visit_year: item.last,
  159. no_of_visits: item.visits,
  160. visited: item.visits > 0,
  161. });
  162. navigation.navigate(
  163. ...([
  164. NAVIGATION_PAGES.REGION_PREVIEW,
  165. {
  166. regionId: item.id,
  167. isTravelsScreen: true,
  168. type: 'nm',
  169. disabled: token ? false : true,
  170. }
  171. ] as never)
  172. )}}>
  173. <NmRegionItem
  174. item={item}
  175. openEditModal={handleOpenEditModal}
  176. updateNM={handleUpdateNM}
  177. token={token}
  178. />
  179. </TouchableOpacity>
  180. );
  181. return (
  182. <PageWrapper>
  183. <Header
  184. label="Regions"
  185. // rightElement={
  186. // <TouchableOpacity
  187. // onPress={() => navigation.navigate(NAVIGATION_PAGES.REGIONS_INFO as never)}
  188. // style={{ width: 30 }}
  189. // >
  190. // <InfoIcon />
  191. // </TouchableOpacity>
  192. // }
  193. />
  194. <TouchableOpacity style={styles.megaSelector} onPress={() => setMegaSelectorVisible(true)}>
  195. <Text style={styles.megaButtonText}>{selectedMega?.name}</Text>
  196. <ChevronIcon width={18} height={18} />
  197. </TouchableOpacity>
  198. {token && (
  199. <View style={styles.buttonContainer}>
  200. <CustomButton
  201. title="All"
  202. onPress={() => setContentIndex(0)}
  203. isActive={contentIndex === 0}
  204. />
  205. <CustomButton
  206. title="Not visited"
  207. onPress={() => setContentIndex(1)}
  208. isActive={contentIndex === 1}
  209. />
  210. <CustomButton
  211. title="Visited"
  212. onPress={() => setContentIndex(2)}
  213. isActive={contentIndex === 2}
  214. />
  215. </View>
  216. )}
  217. <View style={styles.progressHeader}>
  218. <Text style={styles.textSmall}>Visited regions</Text>
  219. <Text style={styles.textSmall}>
  220. {nmRegions?.length
  221. ? `${total}/${nmRegions.length} • ${((total * 100) / nmRegions.length).toFixed(2)}%`
  222. : '0/0 • 100%'}
  223. </Text>
  224. </View>
  225. <Progress.Bar
  226. progress={nmRegions?.length ? total / nmRegions.length : 1}
  227. width={null}
  228. height={4}
  229. color={Colors.DARK_BLUE}
  230. borderWidth={0}
  231. borderRadius={5}
  232. unfilledColor={Colors.FILL_LIGHT}
  233. />
  234. {filteredNmRegions && (filteredNmRegions?.length || filteredTccRegions?.length) ? (
  235. <FlatList
  236. data={filteredNmRegions}
  237. renderItem={renderItem}
  238. keyExtractor={(item) => item.id.toString()}
  239. showsVerticalScrollIndicator={false}
  240. style={{ paddingVertical: 8 }}
  241. ListFooterComponent={
  242. filteredTccRegions && filteredTccRegions.length ? (
  243. <View style={{ marginVertical: 8 }}>
  244. <Text style={[styles.textMedium, { textAlign: 'center' }]}>TCC regions</Text>
  245. {filteredTccRegions?.map((item) => (
  246. <RegionItem
  247. item={item}
  248. updateRegion={handleUpdateTCC}
  249. key={item.id}
  250. token={token}
  251. />
  252. ))}
  253. </View>
  254. ) : null
  255. }
  256. />
  257. ) : null}
  258. <MegaregionsModal
  259. isVisible={megaSelectorVisible}
  260. onClose={() => setMegaSelectorVisible(false)}
  261. onSelect={(object) => {
  262. setMegaSelectorVisible(false);
  263. setSelectedMega(object);
  264. }}
  265. data={megaregions?.data ?? []}
  266. />
  267. <EditNmModal
  268. isVisible={isEditModalVisible}
  269. onClose={() => setIsEditModalVisible(false)}
  270. modalState={modalState}
  271. updateModalState={handleModalStateChange}
  272. updateNM={handleUpdateNM}
  273. />
  274. </PageWrapper>
  275. );
  276. };
  277. export default RegionsScreen;