index.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. import React, { FC, useCallback, useEffect, useState } from 'react';
  2. import { View, Text, Image, TouchableOpacity, Platform } from 'react-native';
  3. import { styles } from './styles';
  4. import {
  5. Button,
  6. CustomImageViewer,
  7. EditNmModal,
  8. HorizontalTabView,
  9. Loading,
  10. Modal as ReactModal
  11. } from 'src/components';
  12. import { CommonActions, useFocusEffect } from '@react-navigation/native';
  13. import { Colors } from 'src/theme';
  14. import { styles as ButtonStyles } from 'src/components/RegionPopup/style';
  15. import * as ImagePicker from 'expo-image-picker';
  16. import { usePostSetToggleItem } from '@api/series';
  17. import { ScrollView } from 'react-native-gesture-handler';
  18. import { NAVIGATION_PAGES } from 'src/types';
  19. import { API_HOST } from 'src/constants';
  20. import { useGetDareRegionDataQuery, useGetNmRegionDataQuery } from '@api/regions';
  21. import { StoreType, storage } from 'src/storage';
  22. import { ButtonVariants } from 'src/types/components';
  23. import { qualityOptions } from '../../TravelsScreen/utils/constants';
  24. import moment from 'moment';
  25. import { useRegion } from 'src/contexts/RegionContext';
  26. import formatNumber from '../../TravelsScreen/utils/formatNumber';
  27. import { PhotosData, Props, SeriesData, SeriesGroup, SeriesItem } from './types';
  28. import ImageCarousel from './ImageCarousel';
  29. import TravelSeriesList from './TravelSeriesList';
  30. import MarkIcon from 'assets/icons/mark.svg';
  31. import ChevronLeft from 'assets/icons/chevron-left.svg';
  32. import CaseSvg from 'assets/icons/briefcase.svg';
  33. import HouseSvg from 'assets/icons/house.svg';
  34. import EditSvg from 'assets/icons/travels-screens/pen-to-square.svg';
  35. import CalendarSvg from 'assets/icons/travels-screens/calendar.svg';
  36. import RotateSvg from 'assets/icons/travels-screens/rotate.svg';
  37. import MapSvg from 'assets/icons/travels-screens/map-location.svg';
  38. import AddImgSvg from 'assets/icons/travels-screens/add-img.svg';
  39. import { useGetTempQuery } from '@api/photos';
  40. const RegionViewScreen: FC<Props> = ({ navigation, route }) => {
  41. const regionId = route.params?.regionId;
  42. const type = route.params?.type;
  43. const disabled = route.params?.disabled;
  44. const token = (storage.get('token', StoreType.STRING) as string) ?? null;
  45. const [isLoading, setIsLoading] = useState(true);
  46. const [isModalVisible, setModalVisible] = useState(false);
  47. const [currentImageIndex, setCurrentImageIndex] = useState(0);
  48. const [activeIndex, setActiveIndex] = useState(0);
  49. const [indexSeries, setIndexSeries] = useState(0);
  50. const [routes, setRoutes] = useState<SeriesGroup[]>([]);
  51. const [series, setSeries] = useState<SeriesData[]>([]);
  52. const [photos, setPhotos] = useState<PhotosData[]>([]);
  53. const [name, setName] = useState(['', '']);
  54. const { data, refetch: refetchData, isFetchedAfterMount } =
  55. type === 'nm'
  56. ? useGetNmRegionDataQuery(regionId, type === 'nm', token && token)
  57. : useGetDareRegionDataQuery(regionId, type === 'dare', token && token);
  58. const { mutate: updateSeriesItem } = usePostSetToggleItem();
  59. const [isInfoModalVisible, setIsInfoModalVisible] = useState<boolean>(false);
  60. const [infoItem, setInfoItem] = useState<SeriesItem | null>(null);
  61. const [isEditModalVisible, setIsEditModalVisible] = useState(false);
  62. const [modalState, setModalState] = useState({
  63. selectedFirstYear: 2021,
  64. selectedLastYear: 2021,
  65. selectedQuality: qualityOptions[2],
  66. selectedNoOfVisits: 1,
  67. years: [],
  68. id: regionId
  69. });
  70. const { data: tempData, refetch } = useGetTempQuery(token, token ? true : false);
  71. const {
  72. handleUpdateNM: updateNM,
  73. handleUpdateDare: updateDare,
  74. userData: regionData,
  75. setUserData: setRegionData,
  76. handleUpdateNMList,
  77. handleUpdateDareList
  78. } = useRegion();
  79. useEffect(() => {
  80. navigation.getParent()?.setOptions({
  81. tabBarStyle: {
  82. display: 'flex',
  83. ...Platform.select({
  84. android: {
  85. // height: 58
  86. }
  87. })
  88. }
  89. });
  90. }, [navigation]);
  91. useFocusEffect(
  92. useCallback(() => {
  93. const fetchGroups = async () => {
  94. let staticGroups = [
  95. {
  96. key: 'all',
  97. title: 'All',
  98. series_id: 0
  99. }
  100. ];
  101. const routesData = data?.data?.series?.map((item) => ({
  102. key: item.series_id?.toString(),
  103. title: item.series_name,
  104. series_id: item.series_id,
  105. icon: item.icon,
  106. items: item.items
  107. }));
  108. routesData && staticGroups.push(...routesData);
  109. setPhotos(
  110. data?.data?.photos?.slice(0, 100).map((item) => ({
  111. ...item,
  112. uriSmall: `${API_HOST}/ajax/pic/${item.id}/small`,
  113. uri: `${API_HOST}/ajax/pic/${item.id}/full`
  114. })) ?? []
  115. );
  116. const [regionName, ...rest] = data?.data?.region_name?.split(/ – | - /) ?? [];
  117. const subname = rest?.join(' - ');
  118. setName([regionName, subname]);
  119. setSeries(data?.data?.series || []);
  120. setRoutes(staticGroups);
  121. if (regionData?.id !== regionId) {
  122. setRegionData({ ...(data?.data || {}), type });
  123. }
  124. setIsLoading(false);
  125. };
  126. if (data && data.result === 'OK') {
  127. fetchGroups();
  128. }
  129. }, [data])
  130. );
  131. useFocusEffect(
  132. useCallback(() => {
  133. refetchData()
  134. }, [navigation, token])
  135. );
  136. useEffect(() => {
  137. if (data && data.data) {
  138. setRegionData({ ...(data?.data || {}), type });
  139. }
  140. }, [isFetchedAfterMount])
  141. const handleCheckboxChange = useCallback(
  142. async (item: SeriesItem, double: boolean, seriesId: number) => {
  143. setSeries((currentData) => {
  144. const groupIndex = currentData.findIndex((group) => group?.series_id === seriesId);
  145. if (groupIndex === -1) return currentData;
  146. const newData = [...currentData];
  147. const newGroup = { ...newData[groupIndex] };
  148. newGroup.items = newGroup.items.map((subItem) =>
  149. subItem.id === item.id
  150. ? {
  151. ...subItem,
  152. ...(double
  153. ? { visited_double: subItem.visited_double === 0 ? 1 : 0 }
  154. : { visited: subItem.visited === 0 ? 1 : 0 })
  155. }
  156. : subItem
  157. );
  158. newData[groupIndex] = newGroup;
  159. return newData;
  160. });
  161. const itemData = {
  162. token: token,
  163. series_id: seriesId,
  164. item_id: item.id,
  165. checked: (item.visited === 1 ? 0 : 1) as 0 | 1,
  166. double: (double && !item.visited_double ? 1 : 0) as 0 | 1
  167. };
  168. try {
  169. updateSeriesItem(itemData);
  170. } catch (error) {
  171. console.error('Failed to update checkbox state', error);
  172. }
  173. },
  174. [token, updateSeriesItem]
  175. );
  176. const handleModalStateChange = (updates: { [key: string]: any }) => {
  177. setModalState((prevState) => ({ ...prevState, ...updates }));
  178. };
  179. useEffect(() => {
  180. const currentYear = moment().year();
  181. let yearSelector: { label: string; value: number }[] = [{ label: 'visited', value: 1 }];
  182. for (let i = currentYear; i >= 1951; i--) {
  183. yearSelector.push({ label: i.toString(), value: i });
  184. }
  185. handleModalStateChange({ years: yearSelector });
  186. }, []);
  187. const openModal = (index: number) => {
  188. setCurrentImageIndex(index);
  189. setModalVisible(true);
  190. };
  191. if (isLoading) return <Loading />;
  192. const handleOpenEditModal = () => {
  193. // handleModalStateChange({
  194. // selectedFirstYear: regionData?.first_visit_year,
  195. // selectedLastYear: regionData?.last_visit_year,
  196. // selectedQuality:
  197. // qualityOptions.find((quality) => quality.id === regionData?.best_visit_quality) ||
  198. // qualityOptions[2],
  199. // selectedNoOfVisits: regionData?.no_of_visits || 1,
  200. // id: regionId
  201. // });
  202. // setIsEditModalVisible(true);
  203. // navigation.navigate(NAVIGATION_PAGES.EDIT_NM_DATA, { regionId: regionId });
  204. let regionName = name[0];
  205. if (name[1]) {
  206. regionName = name.join(' - ');
  207. }
  208. navigation.navigate(NAVIGATION_PAGES.TRIPS_2025, {
  209. region: { id: regionId, name: regionName }
  210. });
  211. };
  212. const handleUpdateNmModal = (
  213. region: number = regionId,
  214. first: number,
  215. last: number,
  216. visits: number,
  217. quality: number
  218. ) => {
  219. const updatedNM = {
  220. ...regionData,
  221. first_visit_year: first,
  222. last_visit_year: last,
  223. best_visit_quality: quality,
  224. no_of_visits: visits,
  225. visited: visits > 0 ? true : false
  226. };
  227. route.params?.isTravelsScreen
  228. ? handleUpdateNMList(region, first, last, visits, quality)
  229. : updateNM(region, first, last, visits, quality);
  230. updatedNM && setRegionData(updatedNM);
  231. };
  232. const handleUpdateNm = () => {
  233. route.params?.isTravelsScreen
  234. ? handleUpdateNMList(
  235. regionId,
  236. regionData.visited ? 0 : 1,
  237. regionData.visited ? 0 : 1,
  238. regionData.visited ? 0 : 1,
  239. 3
  240. )
  241. : updateNM(
  242. regionId,
  243. regionData.visited ? 0 : 1,
  244. regionData.visited ? 0 : 1,
  245. regionData.visited ? 0 : 1,
  246. 3
  247. );
  248. setRegionData({
  249. ...regionData,
  250. first_visit_year: regionData.visited ? 0 : 1,
  251. last_visit_year: regionData.visited ? 0 : 1,
  252. best_visit_quality: 3,
  253. no_of_visits: regionData.visited ? 0 : 1,
  254. visited: !regionData.visited
  255. });
  256. };
  257. const handleUpdateDare = () => {
  258. route.params?.isTravelsScreen
  259. ? handleUpdateDareList(regionId, regionData.visited ? 0 : 1)
  260. : updateDare(regionId, regionData.visited ? 0 : 1);
  261. setRegionData({
  262. ...regionData,
  263. first_visit_year: regionData.visited ? 0 : 1,
  264. last_visit_year: regionData.visited ? 0 : 1,
  265. best_visit_quality: 3,
  266. no_of_visits: regionData.visited ? 0 : 1,
  267. visited: !regionData.visited
  268. });
  269. };
  270. const handleImagePick = async () => {
  271. setIsLoading(true);
  272. const photosData = {
  273. id: regionId,
  274. country: name[0],
  275. name: name[1],
  276. flag: '',
  277. nm: type === 'nm',
  278. dare: type === 'dare',
  279. photos: []
  280. };
  281. await refetch().then(async (temp) => {
  282. if (temp.data?.photos && temp.data?.photos.length > 0) {
  283. setIsLoading(false);
  284. navigation.navigate(
  285. ...([
  286. NAVIGATION_PAGES.ADD_PHOTO,
  287. {
  288. data: photosData,
  289. images: [],
  290. allRegions: [],
  291. tempData: temp.data.photos
  292. }
  293. ] as never)
  294. );
  295. } else {
  296. setIsLoading(false);
  297. let result = await ImagePicker.launchImageLibraryAsync({
  298. mediaTypes: ImagePicker.MediaTypeOptions.Images,
  299. quality: 1,
  300. allowsMultipleSelection: true,
  301. exif: true
  302. });
  303. if (!result.canceled) {
  304. navigation.navigate(
  305. ...([
  306. NAVIGATION_PAGES.ADD_PHOTO,
  307. {
  308. data: photosData,
  309. images: result.assets,
  310. allRegions: []
  311. }
  312. ] as never)
  313. );
  314. }
  315. }
  316. });
  317. };
  318. return (
  319. <View style={styles.container}>
  320. <TouchableOpacity
  321. onPress={() => {
  322. navigation.goBack();
  323. }}
  324. style={styles.backButton}
  325. >
  326. <View style={styles.chevronWrapper}>
  327. <ChevronLeft fill={Colors.WHITE} />
  328. </View>
  329. </TouchableOpacity>
  330. <ScrollView
  331. contentContainerStyle={{}}
  332. nestedScrollEnabled={true}
  333. showsVerticalScrollIndicator={false}
  334. >
  335. {photos.length > 0 ? (
  336. <ImageCarousel
  337. photos={photos}
  338. activeIndex={activeIndex}
  339. setActiveIndex={setActiveIndex}
  340. openModal={openModal}
  341. />
  342. ) : (
  343. <View style={styles.emptyImage}>
  344. <Image
  345. source={require('../../../../../assets/images/logo-opacity.png')}
  346. style={{ width: 100, height: 100 }}
  347. />
  348. <Text style={styles.emptyImageText}>No image available at this location</Text>
  349. </View>
  350. )}
  351. {regionData?.visited ? (
  352. <TouchableOpacity onPress={handleImagePick} style={styles.addPhotoButton}>
  353. <View style={styles.chevronWrapper}>
  354. <AddImgSvg fill={Colors.WHITE} width={20} height={20} />
  355. </View>
  356. </TouchableOpacity>
  357. ) : null}
  358. <TouchableOpacity
  359. onPress={() => {
  360. route.params?.isTravelsScreen || route.params?.isProfileScreen
  361. ? navigation.dispatch(
  362. CommonActions.reset({
  363. index: 1,
  364. routes: [
  365. {
  366. name: NAVIGATION_PAGES.IN_APP_MAP_TAB,
  367. state: {
  368. routes: [
  369. {
  370. name: NAVIGATION_PAGES.MAP_TAB,
  371. params: { id: regionId, type: type === 'nm' ? 'regions' : 'places' }
  372. }
  373. ]
  374. }
  375. }
  376. ]
  377. })
  378. )
  379. : navigation.goBack();
  380. }}
  381. style={styles.goToMapBtn}
  382. >
  383. <View style={styles.chevronWrapper}>
  384. <MapSvg fill={Colors.WHITE} />
  385. </View>
  386. </TouchableOpacity>
  387. <View style={{ gap: 16 }}>
  388. <View
  389. style={[styles.margin, { flexDirection: 'row', gap: 8, justifyContent: 'flex-end' }]}
  390. >
  391. {regionData?.visited && regionData?.first_visit_year > 1 && !disabled && (
  392. <View style={styles.infoContent}>
  393. <CalendarSvg height={18} width={18} fill={Colors.DARK_BLUE} />
  394. <Text style={styles.visitedButtonText}>{regionData?.first_visit_year}</Text>
  395. </View>
  396. )}
  397. {regionData?.visited && type === 'nm' && !disabled && (
  398. <View style={styles.infoContent}>
  399. <RotateSvg fill={Colors.DARK_BLUE} />
  400. <Text style={styles.visitedButtonText}>
  401. {regionData.no_of_visits >= 10 ? '10+' : regionData.no_of_visits}
  402. </Text>
  403. </View>
  404. )}
  405. </View>
  406. <View style={[styles.nameContainer, styles.margin]}>
  407. <Text style={styles.title}>{name[0]}</Text>
  408. <View style={ButtonStyles.btnContainer}>
  409. {/* {regionData?.visited &&
  410. type === 'nm' &&
  411. !disabled &&
  412. regionData?.no_of_visits === 1 ? (
  413. <TouchableOpacity onPress={handleOpenEditModal} style={ButtonStyles.editBtn}>
  414. <EditSvg width={14} height={14} />
  415. </TouchableOpacity>
  416. ) : null} */}
  417. {regionData.future ? (
  418. <View style={{ flex: 1 }}>
  419. <Text
  420. style={{
  421. fontSize: 10,
  422. fontWeight: '500',
  423. color: Colors.DARK_BLUE,
  424. flexShrink: 1,
  425. fontStyle: 'italic'
  426. }}
  427. >
  428. Visits planned in the future
  429. </Text>
  430. </View>
  431. ) : null}
  432. {!disabled ? (
  433. <TouchableOpacity
  434. style={[
  435. ButtonStyles.btn,
  436. (regionData?.visited || regionData.edit_in_trips === 1) && !disabled
  437. ? ButtonStyles.visitedButton
  438. : ButtonStyles.markVisitedButton
  439. ]}
  440. onPress={() => {
  441. if (regionData?.type === 'nm' && regionData?.edit_in_trips === 1) {
  442. handleOpenEditModal();
  443. return;
  444. }
  445. type === 'nm' ? handleUpdateNm() : handleUpdateDare();
  446. }}
  447. >
  448. {regionData.edit_in_trips === 1 && !disabled && regionData?.type === 'nm' ? (
  449. <View style={ButtonStyles.visitedContainer}>
  450. <EditSvg width={14} height={14} />
  451. <Text style={ButtonStyles.visitedButtonText}>Edit</Text>
  452. </View>
  453. ) : regionData?.visited ? (
  454. <View style={ButtonStyles.visitedContainer}>
  455. <MarkIcon width={16} height={16} />
  456. <Text style={ButtonStyles.visitedButtonText}>Visited</Text>
  457. </View>
  458. ) : (
  459. <Text style={[ButtonStyles.markVisitedButtonText]}>Mark Visited</Text>
  460. )}
  461. </TouchableOpacity>
  462. ) : null}
  463. </View>
  464. </View>
  465. <Text style={[styles.subtitle, styles.margin]}>{name[1]}</Text>
  466. <View style={[styles.divider, styles.margin]} />
  467. <View style={[styles.stats, styles.margin]}>
  468. {(data?.data.users_from_region_count ?? 0 > 0) ? (
  469. <TouchableOpacity
  470. style={[styles.statItem, { justifyContent: 'flex-start' }]}
  471. onPress={() =>
  472. navigation.navigate(
  473. ...([
  474. NAVIGATION_PAGES.USERS_LIST,
  475. {
  476. id: regionId,
  477. isFromHere: true,
  478. type: 'nm'
  479. }
  480. ] as never)
  481. )
  482. }
  483. >
  484. <View style={styles.icon}>
  485. <HouseSvg />
  486. </View>
  487. <View
  488. style={{
  489. height: 12,
  490. width: 1,
  491. backgroundColor: Colors.DARK_BLUE,
  492. marginRight: 6
  493. }}
  494. />
  495. <View style={styles.userImageContainer}>
  496. {data?.data.users_from_region &&
  497. data?.data.users_from_region.length > 0 &&
  498. data?.data.users_from_region?.map((user, index: number) => (
  499. <Image
  500. key={index}
  501. source={{ uri: API_HOST + user }}
  502. style={styles.userImage}
  503. />
  504. ))}
  505. <View style={styles.userCountContainer}>
  506. <Text style={styles.userCount}>
  507. {formatNumber(data?.data?.users_from_region_count ?? 0)}
  508. </Text>
  509. </View>
  510. </View>
  511. </TouchableOpacity>
  512. ) : (
  513. <View style={[styles.statItem, { justifyContent: 'flex-start' }]} />
  514. )}
  515. {(data?.data.users_who_visited_region_count ?? 0 > 0) ? (
  516. <TouchableOpacity
  517. style={[styles.statItem, { justifyContent: 'flex-end' }]}
  518. onPress={() =>
  519. navigation.navigate(
  520. ...([
  521. NAVIGATION_PAGES.USERS_LIST,
  522. {
  523. id: regionId,
  524. isFromHere: false,
  525. type
  526. }
  527. ] as never)
  528. )
  529. }
  530. >
  531. <View style={styles.icon}>
  532. <CaseSvg />
  533. </View>
  534. <View
  535. style={{
  536. height: 12,
  537. width: 1,
  538. backgroundColor: Colors.DARK_BLUE,
  539. marginRight: 6
  540. }}
  541. />
  542. <View style={styles.userImageContainer}>
  543. {data?.data.users_who_visited_region &&
  544. data?.data.users_who_visited_region.length > 0 &&
  545. data?.data.users_who_visited_region?.map((user, index) => (
  546. <Image
  547. key={index}
  548. source={{ uri: API_HOST + user }}
  549. style={[styles.userImage]}
  550. />
  551. ))}
  552. <View style={styles.userCountContainer}>
  553. <Text style={styles.userCount}>
  554. {formatNumber(data?.data.users_who_visited_region_count ?? 0)}
  555. </Text>
  556. </View>
  557. </View>
  558. </TouchableOpacity>
  559. ) : (
  560. <View style={[styles.statItem, { justifyContent: 'flex-end' }]} />
  561. )}
  562. </View>
  563. <View style={[styles.divider, styles.margin, { marginBottom: 8 }]} />
  564. {series.length > 0 ? (
  565. <>
  566. <Text style={[styles.travelSeriesTitle, styles.margin]}>TRAVEL SERIES</Text>
  567. <HorizontalTabView
  568. index={indexSeries}
  569. setIndex={setIndexSeries}
  570. routes={routes}
  571. renderScene={({ route }: { route: any }) => <View style={{ height: 0 }} />}
  572. maxTabHeight={50}
  573. />
  574. <View style={styles.margin}>
  575. <TravelSeriesList
  576. series={series}
  577. indexSeries={indexSeries}
  578. routes={routes}
  579. handleCheckboxChange={handleCheckboxChange}
  580. setIsInfoModalVisible={setIsInfoModalVisible}
  581. setInfoItem={setInfoItem}
  582. disabled={disabled}
  583. />
  584. </View>
  585. </>
  586. ) : null}
  587. </View>
  588. <CustomImageViewer
  589. images={photos}
  590. imageIndex={currentImageIndex}
  591. visible={isModalVisible}
  592. onRequestClose={() => setModalVisible(false)}
  593. onImageIndexChange={setActiveIndex}
  594. backgroundColor={Colors.DARK_BLUE}
  595. renderFooter={(imageIndex: number) => (
  596. <View style={styles.imageFooter}>
  597. <Text style={styles.imageDescription}>{photos[imageIndex].title}</Text>
  598. <TouchableOpacity
  599. onPress={() => {
  600. setModalVisible(false);
  601. navigation.navigate(
  602. ...([
  603. NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW,
  604. { userId: photos[imageIndex].user_id, hideTabBar: true }
  605. ] as never)
  606. );
  607. }}
  608. disabled={disabled}
  609. style={styles.imageOwner}
  610. >
  611. <Text style={styles.imageOwnerText}>{photos[imageIndex].first_name}</Text>
  612. <Text style={styles.imageOwnerText}>{photos[imageIndex].last_name}</Text>
  613. </TouchableOpacity>
  614. </View>
  615. )}
  616. />
  617. <ReactModal
  618. visible={isInfoModalVisible}
  619. children={
  620. <View style={styles.modalView}>
  621. <Text style={styles.infoTitle}>{infoItem?.name}</Text>
  622. <Text style={styles.infoText}>{infoItem?.description}</Text>
  623. <Button
  624. variant={ButtonVariants.OPACITY}
  625. containerStyles={styles.btnContainer}
  626. textStyles={{
  627. color: Colors.DARK_BLUE
  628. }}
  629. onPress={() => setIsInfoModalVisible(false)}
  630. children={'Got it'}
  631. />
  632. </View>
  633. }
  634. onRequestClose={() => setIsInfoModalVisible(false)}
  635. headerTitle={'Info'}
  636. visibleInPercent={'auto'}
  637. />
  638. </ScrollView>
  639. <EditNmModal
  640. isVisible={isEditModalVisible}
  641. onClose={() => setIsEditModalVisible(false)}
  642. modalState={modalState}
  643. updateModalState={handleModalStateChange}
  644. updateNM={handleUpdateNmModal}
  645. />
  646. </View>
  647. );
  648. };
  649. export default RegionViewScreen;