|
|
@@ -1,13 +1,24 @@
|
|
|
-import React, { useCallback, useEffect, useState } from 'react';
|
|
|
-import { View, Text, Image, TouchableOpacity, ScrollView, Dimensions, Switch } from 'react-native';
|
|
|
+import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
+import {
|
|
|
+ View,
|
|
|
+ Text,
|
|
|
+ Image,
|
|
|
+ TouchableOpacity,
|
|
|
+ ScrollView,
|
|
|
+ Dimensions,
|
|
|
+ Switch,
|
|
|
+ Pressable,
|
|
|
+ Animated
|
|
|
+} from 'react-native';
|
|
|
import { Colors } from 'src/theme';
|
|
|
import { styles } from './styles';
|
|
|
import { Loading } from 'src/components';
|
|
|
|
|
|
import CheckSvg from 'assets/icons/mark.svg';
|
|
|
import CloseSVG from 'assets/icons/close.svg';
|
|
|
+import ArrowIcon from 'assets/icons/mark-to-up.svg';
|
|
|
import { API_HOST } from 'src/constants';
|
|
|
-import { FlashList } from '@shopify/flash-list';
|
|
|
+import { FlashList, FlashListRef } from '@shopify/flash-list';
|
|
|
import { useNavigation } from '@react-navigation/native';
|
|
|
import { NAVIGATION_PAGES } from 'src/types';
|
|
|
|
|
|
@@ -49,15 +60,35 @@ const RegionsRenderer = ({
|
|
|
minimumViewTime: 1000
|
|
|
};
|
|
|
const isSmallWidth = Dimensions.get('window').width < 383;
|
|
|
- const [showAll, setShowAll] = useState(true);
|
|
|
+ const [showAll, setShowAll] = useState<'all' | 'visited' | 'not_visited'>('all');
|
|
|
const [filteredRegions, setFilteredRegions] = useState<any[]>([]);
|
|
|
const [filteredMegaregions, setFilteredMegaregions] = useState<any[]>([]);
|
|
|
const disabled = type === 'whs' || type === 'tcc' ? true : false;
|
|
|
|
|
|
+ const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
|
+
|
|
|
+ const animation = useRef(new Animated.Value(0)).current;
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ Animated.timing(animation, {
|
|
|
+ toValue: dropdownOpen ? 1 : 0,
|
|
|
+ duration: 100,
|
|
|
+ useNativeDriver: true
|
|
|
+ }).start();
|
|
|
+ }, [dropdownOpen]);
|
|
|
+
|
|
|
+ const showAllLabels: Record<'all' | 'visited' | 'not_visited', string> = {
|
|
|
+ all: 'All',
|
|
|
+ visited: 'Visited',
|
|
|
+ not_visited: 'Not Visited'
|
|
|
+ };
|
|
|
+
|
|
|
+ const flashListRef = useRef<FlashListRef<any> | null>(null);
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
if (!regions?.data) return;
|
|
|
|
|
|
- if (showAll) {
|
|
|
+ if (showAll === 'all') {
|
|
|
switch (type) {
|
|
|
case 'nm':
|
|
|
case 'mqp':
|
|
|
@@ -74,7 +105,7 @@ const RegionsRenderer = ({
|
|
|
setFilteredRegions(regions.data);
|
|
|
break;
|
|
|
}
|
|
|
- } else {
|
|
|
+ } else if (showAll === 'visited') {
|
|
|
switch (type) {
|
|
|
case 'nm':
|
|
|
case 'mqp':
|
|
|
@@ -102,6 +133,38 @@ const RegionsRenderer = ({
|
|
|
setFilteredRegions(regions.data.filter((item: any) => item.visited));
|
|
|
break;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ switch (type) {
|
|
|
+ case 'nm':
|
|
|
+ case 'mqp':
|
|
|
+ const filteredMegaregions = regions.data?.megaregions
|
|
|
+ ?.map((item: Mega) => ({
|
|
|
+ ...item,
|
|
|
+ regions: item.regions.filter((region) => !item.visits.includes(region.id)),
|
|
|
+ total: item.regions.length
|
|
|
+ }))
|
|
|
+ ?.filter((item: Mega) => item.regions.length > 0);
|
|
|
+
|
|
|
+ setFilteredMegaregions(filteredMegaregions);
|
|
|
+ break;
|
|
|
+ case 'un':
|
|
|
+ case 'unp':
|
|
|
+ case 'tcc':
|
|
|
+ setFilteredRegions(
|
|
|
+ regions.data[0].filter((item: Region) => !regions.data[1].includes(item.name))
|
|
|
+ );
|
|
|
+ break;
|
|
|
+ case 'slow':
|
|
|
+ setFilteredRegions(regions.data[0].filter((item: any) => item.visited === 0));
|
|
|
+ break;
|
|
|
+ case 'whs':
|
|
|
+ setFilteredRegions(regions.data.filter((item: any) => !item.visited));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flashListRef && flashListRef.current) {
|
|
|
+ flashListRef.current?.scrollToOffset({ offset: 0, animated: false });
|
|
|
}
|
|
|
}, [showAll, regions]);
|
|
|
|
|
|
@@ -337,17 +400,122 @@ const RegionsRenderer = ({
|
|
|
onRequestClose={() => setIsModalVisible(false)}
|
|
|
rightElement={
|
|
|
rightElement ? (
|
|
|
- <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
|
- <Text style={{ color: Colors.DARK_BLUE, fontSize: 12, fontWeight: '600' }}>
|
|
|
- Show/Hide All
|
|
|
- </Text>
|
|
|
- <Switch
|
|
|
- trackColor={{ false: Colors.LIGHT_GRAY, true: Colors.DARK_BLUE }}
|
|
|
- thumbColor={Colors.WHITE}
|
|
|
- onValueChange={() => setShowAll(!showAll)}
|
|
|
- value={showAll}
|
|
|
- style={{ transform: 'scale(0.8)' }}
|
|
|
- />
|
|
|
+ <View style={{ alignItems: 'flex-end' }}>
|
|
|
+ <Pressable
|
|
|
+ onPress={() => setDropdownOpen((prev) => !prev)}
|
|
|
+ style={{
|
|
|
+ paddingHorizontal: 10,
|
|
|
+ paddingVertical: 6,
|
|
|
+ borderRadius: 6,
|
|
|
+ borderWidth: 1,
|
|
|
+ borderColor: Colors.BORDER_LIGHT,
|
|
|
+ flexDirection: 'row',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'space-between',
|
|
|
+ minWidth: 110
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ fontSize: 12,
|
|
|
+ fontWeight: '600',
|
|
|
+ color: Colors.DARK_BLUE,
|
|
|
+ marginRight: 6
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {showAllLabels[showAll]}
|
|
|
+ </Text>
|
|
|
+
|
|
|
+ <Animated.View
|
|
|
+ style={{
|
|
|
+ transform: [
|
|
|
+ {
|
|
|
+ rotate: animation.interpolate({
|
|
|
+ inputRange: [0, 1],
|
|
|
+ outputRange: ['0deg', '180deg']
|
|
|
+ })
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <ArrowIcon height={12} width={12} stroke={Colors.BORDER_LIGHT} />
|
|
|
+ </Animated.View>
|
|
|
+ </Pressable>
|
|
|
+
|
|
|
+ {dropdownOpen && (
|
|
|
+ <Pressable
|
|
|
+ onPress={() => setDropdownOpen(false)}
|
|
|
+ style={{
|
|
|
+ position: 'absolute',
|
|
|
+ top: -1000,
|
|
|
+ left: -1000,
|
|
|
+ right: -1000,
|
|
|
+ bottom: -1000,
|
|
|
+ zIndex: 1
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {dropdownOpen && (
|
|
|
+ <Animated.View
|
|
|
+ pointerEvents="auto"
|
|
|
+ style={{
|
|
|
+ position: 'absolute',
|
|
|
+ top: 36,
|
|
|
+ right: 0,
|
|
|
+ backgroundColor: Colors.WHITE,
|
|
|
+ borderRadius: 8,
|
|
|
+ paddingVertical: 6,
|
|
|
+ minWidth: 150,
|
|
|
+ borderWidth: 1,
|
|
|
+ borderColor: Colors.BORDER_LIGHT,
|
|
|
+ opacity: animation,
|
|
|
+ zIndex: 1000,
|
|
|
+ elevation: 10,
|
|
|
+ transform: [
|
|
|
+ {
|
|
|
+ translateY: animation.interpolate({
|
|
|
+ inputRange: [0, 1],
|
|
|
+ outputRange: [-6, 0]
|
|
|
+ })
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {(Object.keys(showAllLabels) as Array<'all' | 'visited' | 'not_visited'>).map(
|
|
|
+ (key) => (
|
|
|
+ <Pressable
|
|
|
+ key={key}
|
|
|
+ onPress={() => {
|
|
|
+ setShowAll(key);
|
|
|
+ setDropdownOpen(false);
|
|
|
+ }}
|
|
|
+ style={{
|
|
|
+ paddingVertical: 10,
|
|
|
+ paddingHorizontal: 14,
|
|
|
+ flexDirection: 'row',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'space-between'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ fontSize: 13,
|
|
|
+ color: Colors.DARK_BLUE,
|
|
|
+ fontWeight: '600'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {showAllLabels[key]}
|
|
|
+ </Text>
|
|
|
+
|
|
|
+ {showAll === key && (
|
|
|
+ <CheckSvg fill={Colors.DARK_BLUE} height={12} width={12} />
|
|
|
+ )}
|
|
|
+ </Pressable>
|
|
|
+ )
|
|
|
+ )}
|
|
|
+ </Animated.View>
|
|
|
+ )}
|
|
|
</View>
|
|
|
) : null
|
|
|
}
|
|
|
@@ -361,8 +529,8 @@ const RegionsRenderer = ({
|
|
|
<>
|
|
|
{renderHeader(type === 'nm' ? 'NM' : 'DARE', true)}
|
|
|
<FlashList
|
|
|
+ ref={flashListRef}
|
|
|
viewabilityConfig={flashlistConfig}
|
|
|
- estimatedItemSize={4000}
|
|
|
data={filteredMegaregions}
|
|
|
renderItem={renderMegaregion}
|
|
|
keyExtractor={(megaregion) => megaregion?.id?.toString()}
|
|
|
@@ -379,8 +547,8 @@ const RegionsRenderer = ({
|
|
|
<>
|
|
|
{renderHeader(type === 'un' ? 'UN' : type === 'unp' ? 'UN+' : 'TCC', true)}
|
|
|
<FlashList
|
|
|
+ ref={flashListRef}
|
|
|
viewabilityConfig={flashlistConfig}
|
|
|
- estimatedItemSize={50}
|
|
|
data={filteredRegions}
|
|
|
renderItem={(region) => renderRegion(region.item)}
|
|
|
keyExtractor={(region: Region) => region.name}
|
|
|
@@ -406,8 +574,8 @@ const RegionsRenderer = ({
|
|
|
<>
|
|
|
{renderHeader('SLOW', true)}
|
|
|
<FlashList
|
|
|
+ ref={flashListRef}
|
|
|
viewabilityConfig={flashlistConfig}
|
|
|
- estimatedItemSize={50}
|
|
|
data={filteredRegions}
|
|
|
renderItem={(region) => renderRegion(region.item)}
|
|
|
keyExtractor={(region: Region) => region.country_id?.toString()}
|
|
|
@@ -457,8 +625,8 @@ const RegionsRenderer = ({
|
|
|
<>
|
|
|
{renderHeader('YES', false)}
|
|
|
<FlashList
|
|
|
+ ref={flashListRef}
|
|
|
viewabilityConfig={flashlistConfig}
|
|
|
- estimatedItemSize={50}
|
|
|
data={regions.data[0]}
|
|
|
renderItem={(region) => renderRegion(region.item)}
|
|
|
keyExtractor={(region: Region) => region.id?.toString()}
|
|
|
@@ -499,8 +667,8 @@ const RegionsRenderer = ({
|
|
|
<>
|
|
|
{renderHeader('WHS', true)}
|
|
|
<FlashList
|
|
|
+ ref={flashListRef}
|
|
|
viewabilityConfig={flashlistConfig}
|
|
|
- estimatedItemSize={50}
|
|
|
data={filteredRegions}
|
|
|
renderItem={(region) => renderRegion(region.item)}
|
|
|
keyExtractor={(region: Region) => region.name}
|