|
@@ -1,13 +1,18 @@
|
|
|
-import React from 'react';
|
|
|
-import { View, Text, TouchableOpacity } from 'react-native';
|
|
|
-import Modal from 'react-native-modal';
|
|
|
-import CloseSvg from 'assets/icons/close.svg';
|
|
|
-import FilterIcon from 'assets/icons/filter.svg';
|
|
|
+import React, { useEffect, useState } from 'react';
|
|
|
+import { View, Text, TouchableOpacity, Image, Switch } from 'react-native';
|
|
|
+import ReactModal from 'react-native-modal';
|
|
|
import { Colors } from 'src/theme';
|
|
|
import { ModalStyles } from '../../TravellersScreen/Components/styles';
|
|
|
-import { Dropdown } from 'react-native-searchable-dropdown-kj';
|
|
|
+import { Dropdown, MultiSelect } from 'react-native-searchable-dropdown-kj';
|
|
|
import { Button } from 'src/components';
|
|
|
import { ButtonVariants } from 'src/types/components';
|
|
|
+import { styles } from './styles';
|
|
|
+import { TabBar, TabView } from 'react-native-tab-view';
|
|
|
+import { usePostGetMapYearsQuery } from '@api/user';
|
|
|
+import { API_HOST, FASTEST_MAP_HOST } from 'src/constants';
|
|
|
+import CheckSvg from 'assets/icons/mark.svg';
|
|
|
+import { useGetListQuery } from '@api/series';
|
|
|
+import { RadioButton } from 'react-native-paper';
|
|
|
|
|
|
const FilterModal = ({
|
|
|
isFilterVisible,
|
|
@@ -16,7 +21,11 @@ const FilterModal = ({
|
|
|
tilesType,
|
|
|
setTilesType,
|
|
|
type,
|
|
|
- setType
|
|
|
+ setType,
|
|
|
+ userId,
|
|
|
+ setVisitedTiles,
|
|
|
+ setSeriesFilter,
|
|
|
+ isPublicView
|
|
|
}: {
|
|
|
isFilterVisible: boolean;
|
|
|
setIsFilterVisible: (isVisible: boolean) => void;
|
|
@@ -25,28 +34,94 @@ const FilterModal = ({
|
|
|
setTilesType: (item: any) => void;
|
|
|
type: number;
|
|
|
setType: (type: any) => void;
|
|
|
+ userId: number;
|
|
|
+ setVisitedTiles: (tiles: string) => void;
|
|
|
+ setSeriesFilter?: (filter: any) => void;
|
|
|
+ isPublicView: boolean;
|
|
|
}) => {
|
|
|
- return (
|
|
|
- <Modal isVisible={isFilterVisible}>
|
|
|
- <View style={{ backgroundColor: 'white', borderRadius: 15 }}>
|
|
|
- <View style={{ marginHorizontal: '5%', marginTop: '5%', marginBottom: '10%' }}>
|
|
|
- <View style={{ alignSelf: 'flex-end' }}>
|
|
|
- <TouchableOpacity
|
|
|
- onPress={() => {
|
|
|
- type === 0
|
|
|
- ? setTilesType({ label: 'NM regions', value: 0 })
|
|
|
- : setTilesType({ label: 'UN countries', value: 1 });
|
|
|
- setIsFilterVisible(!isFilterVisible);
|
|
|
- }}
|
|
|
- >
|
|
|
- <CloseSvg fill={Colors.LIGHT_GRAY} />
|
|
|
- </TouchableOpacity>
|
|
|
- </View>
|
|
|
- <View style={{ display: 'flex', alignItems: 'center' }}>
|
|
|
- <Text style={{ color: Colors.DARK_BLUE, fontSize: 20, fontWeight: '700' }}>
|
|
|
- Map filter show visited
|
|
|
- </Text>
|
|
|
- <View style={[ModalStyles.ageAndRankingWrapper, { marginTop: 24 }]}>
|
|
|
+ const [index, setIndex] = useState(0);
|
|
|
+ const [selectedYear, setSelectedYear] = useState<{ label: string; value: number } | null>(null);
|
|
|
+ const [allYears, setAllYears] = useState<{ label: string; value: number }[]>([]);
|
|
|
+ const [selectedVisible, setSelectedVisible] = useState({ label: 'visited by', value: 0 });
|
|
|
+ const visibleTypes = [
|
|
|
+ { label: 'visited by', value: 0 },
|
|
|
+ { label: 'visited in', value: 1 }
|
|
|
+ ];
|
|
|
+ const [routes] = useState([
|
|
|
+ { key: 'regions', title: 'NM / UN / DARE' },
|
|
|
+ { key: 'series', title: 'Series' }
|
|
|
+ ]);
|
|
|
+ const { data } = usePostGetMapYearsQuery(userId, true);
|
|
|
+ const { data: seriesList } = useGetListQuery(true);
|
|
|
+ const [series, setSeries] = useState<{ label: string; value: number }[]>([]);
|
|
|
+ const [selectedSeries, setSelectedSeries] = useState<number[]>([]);
|
|
|
+ const [seriesVisible, setSeriesVisible] = useState(true);
|
|
|
+ const [selectedSeriesFilter, setSelectedSeriesFilter] = useState(-1);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (data) {
|
|
|
+ const years = data.data.map_years.filter((year) => year > 1900);
|
|
|
+ const formattedYears = years
|
|
|
+ .map((year) => ({ label: year.toString(), value: year }))
|
|
|
+ .reverse();
|
|
|
+ setAllYears(formattedYears);
|
|
|
+ formattedYears.length && setSelectedYear(formattedYears[0]);
|
|
|
+ }
|
|
|
+ }, [data]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (seriesList?.data) {
|
|
|
+ setSeries([
|
|
|
+ ...seriesList.data.map((item) => ({
|
|
|
+ label: item.name,
|
|
|
+ value: item.id,
|
|
|
+ icon: item.icon
|
|
|
+ }))
|
|
|
+ ]);
|
|
|
+ setSelectedSeries(seriesList.data.map((item) => item.id));
|
|
|
+ }
|
|
|
+ }, [seriesList]);
|
|
|
+
|
|
|
+ if (!data) return;
|
|
|
+
|
|
|
+ const handleApplyFilter = () => {
|
|
|
+ let tileUrl = `${FASTEST_MAP_HOST}/tiles_nm/`;
|
|
|
+ if (!selectedYear) {
|
|
|
+ if (tilesType.value === 0) {
|
|
|
+ tileUrl += 'user_visited/' + userId;
|
|
|
+ } else if (tilesType.value === 1) {
|
|
|
+ tileUrl += 'user_visited_un/' + userId;
|
|
|
+ } else {
|
|
|
+ tileUrl += 'user_visited_dare/' + userId;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (selectedVisible.value === 0) {
|
|
|
+ if (tilesType.value === 0) {
|
|
|
+ tileUrl += 'user_visited_year/' + userId + '/' + selectedYear.value;
|
|
|
+ } else if (tilesType.value === 1) {
|
|
|
+ tileUrl += 'user_visited_un_year/' + userId + '/' + selectedYear.value;
|
|
|
+ } else {
|
|
|
+ tileUrl += 'user_visited_dare/' + userId;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (tilesType.value === 0) {
|
|
|
+ tileUrl += 'user_visited_in_year/' + userId + '/' + selectedYear.value;
|
|
|
+ } else if (tilesType.value === 1) {
|
|
|
+ tileUrl += 'user_visited_un_in_year/' + userId + '/' + selectedYear.value;
|
|
|
+ } else {
|
|
|
+ tileUrl += 'user_visited_dare/' + userId;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setVisitedTiles(tileUrl);
|
|
|
+ };
|
|
|
+
|
|
|
+ const renderScene = ({ route }: { route: any }) => {
|
|
|
+ return route.key === 'regions' ? (
|
|
|
+ <View style={styles.sceneContainer}>
|
|
|
+ <View style={styles.optionsContainer}>
|
|
|
+ <View style={styles.rowWrapper}>
|
|
|
+ <View style={[styles.dropdownWrapper, {}]}>
|
|
|
<Dropdown
|
|
|
style={[ModalStyles.dropdown, { width: '100%' }]}
|
|
|
placeholderStyle={ModalStyles.placeholderStyle}
|
|
@@ -62,43 +137,221 @@ const FilterModal = ({
|
|
|
}}
|
|
|
/>
|
|
|
</View>
|
|
|
- <View style={[ModalStyles.buttonsWrapper, { marginTop: 24 }]}>
|
|
|
- <Button
|
|
|
- variant={ButtonVariants.OPACITY}
|
|
|
- containerStyles={{
|
|
|
- borderColor: Colors.DARK_BLUE,
|
|
|
- backgroundColor: 'white',
|
|
|
- width: '45%'
|
|
|
- }}
|
|
|
- textStyles={{
|
|
|
- color: Colors.DARK_BLUE
|
|
|
- }}
|
|
|
- onPress={() => {
|
|
|
- setTilesType({ label: 'NM regions', value: 0 });
|
|
|
- }}
|
|
|
- children={'Clear'}
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {tilesType.value !== 2 && allYears.length ? (
|
|
|
+ <View style={styles.rowWrapper}>
|
|
|
+ <View style={styles.dropdownWrapper}>
|
|
|
+ <Dropdown
|
|
|
+ style={[ModalStyles.dropdown, { width: '100%' }]}
|
|
|
+ placeholderStyle={ModalStyles.placeholderStyle}
|
|
|
+ selectedTextStyle={ModalStyles.selectedTextStyle}
|
|
|
+ containerStyle={ModalStyles.dropdownContent}
|
|
|
+ data={visibleTypes}
|
|
|
+ labelField="label"
|
|
|
+ valueField="value"
|
|
|
+ value={selectedVisible?.label}
|
|
|
+ placeholder={selectedVisible?.label}
|
|
|
+ onChange={(item) => {
|
|
|
+ setSelectedVisible(item);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ <View style={styles.dropdownWrapper}>
|
|
|
+ <Dropdown
|
|
|
+ style={[ModalStyles.dropdown, { width: '100%' }]}
|
|
|
+ placeholderStyle={ModalStyles.placeholderStyle}
|
|
|
+ selectedTextStyle={ModalStyles.selectedTextStyle}
|
|
|
+ containerStyle={ModalStyles.dropdownContent}
|
|
|
+ data={allYears}
|
|
|
+ labelField="label"
|
|
|
+ valueField="value"
|
|
|
+ value={selectedYear?.label}
|
|
|
+ placeholder={selectedYear?.label}
|
|
|
+ dropdownPosition="top"
|
|
|
+ onChange={(item) => {
|
|
|
+ setSelectedYear(item);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ ) : null}
|
|
|
+ </View>
|
|
|
+ <View style={{ gap: 16 }}>
|
|
|
+ <Button
|
|
|
+ children="Filter"
|
|
|
+ onPress={() => {
|
|
|
+ handleApplyFilter();
|
|
|
+ setType(tilesType.value);
|
|
|
+ setIsFilterVisible(false);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ children="Clear"
|
|
|
+ onPress={() => {
|
|
|
+ setTilesType({ label: 'NM regions', value: 0 });
|
|
|
+ setSelectedYear(allYears[0]);
|
|
|
+ setSelectedVisible({ label: 'visited by', value: 0 });
|
|
|
+ setVisitedTiles(`${FASTEST_MAP_HOST}/tiles_nm/user_visited/${userId}`);
|
|
|
+ setType(0);
|
|
|
+ }}
|
|
|
+ variant={ButtonVariants.OPACITY}
|
|
|
+ containerStyles={styles.closeBtn}
|
|
|
+ textStyles={{ color: Colors.DARK_BLUE }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ ) : (
|
|
|
+ <View style={styles.sceneContainer}>
|
|
|
+ <View style={styles.optionsContainer}>
|
|
|
+ <View style={[styles.row, { gap: 8 }]}>
|
|
|
+ <Switch
|
|
|
+ trackColor={{ false: Colors.LIGHT_GRAY, true: Colors.DARK_BLUE }}
|
|
|
+ thumbColor={Colors.WHITE}
|
|
|
+ onValueChange={setSeriesVisible}
|
|
|
+ value={seriesVisible}
|
|
|
+ style={{ transform: 'scale(0.8)' }}
|
|
|
+ />
|
|
|
+ <Text style={styles.textBold}>Visible / Not visible</Text>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ <View style={[styles.row, { justifyContent: 'space-between' }]}>
|
|
|
+ <TouchableOpacity style={styles.row} onPress={() => setSelectedSeriesFilter(-1)}>
|
|
|
+ <RadioButton.Android
|
|
|
+ value="all"
|
|
|
+ status={selectedSeriesFilter === -1 ? 'checked' : 'unchecked'}
|
|
|
+ onPress={() => setSelectedSeriesFilter(-1)}
|
|
|
+ color={Colors.DARK_BLUE}
|
|
|
/>
|
|
|
- <Button
|
|
|
- variant={ButtonVariants.FILL}
|
|
|
- containerStyles={{
|
|
|
- borderColor: Colors.DARK_BLUE,
|
|
|
- backgroundColor: Colors.DARK_BLUE,
|
|
|
- width: '45%'
|
|
|
- }}
|
|
|
- textStyles={{
|
|
|
- color: Colors.WHITE
|
|
|
- }}
|
|
|
- onPress={() => {
|
|
|
- setType(tilesType.value);
|
|
|
- setIsFilterVisible(false);
|
|
|
- }}
|
|
|
- children={'Filter'}
|
|
|
+ <Text style={styles.textBold}>All items</Text>
|
|
|
+ </TouchableOpacity>
|
|
|
+
|
|
|
+ <TouchableOpacity style={styles.row} onPress={() => setSelectedSeriesFilter(1)}>
|
|
|
+ <RadioButton.Android
|
|
|
+ value="visited"
|
|
|
+ status={selectedSeriesFilter === 1 ? 'checked' : 'unchecked'}
|
|
|
+ onPress={() => setSelectedSeriesFilter(1)}
|
|
|
+ color={Colors.DARK_BLUE}
|
|
|
/>
|
|
|
- </View>
|
|
|
+ <Text style={styles.textBold}>Visited</Text>
|
|
|
+ </TouchableOpacity>
|
|
|
+
|
|
|
+ <TouchableOpacity style={styles.row} onPress={() => setSelectedSeriesFilter(0)}>
|
|
|
+ <RadioButton.Android
|
|
|
+ value="not-visited"
|
|
|
+ status={selectedSeriesFilter === 0 ? 'checked' : 'unchecked'}
|
|
|
+ onPress={() => setSelectedSeriesFilter(0)}
|
|
|
+ color={Colors.DARK_BLUE}
|
|
|
+ />
|
|
|
+ <Text style={styles.textBold}>Not visited</Text>
|
|
|
+ </TouchableOpacity>
|
|
|
</View>
|
|
|
+
|
|
|
+ <MultiSelect
|
|
|
+ style={[ModalStyles.dropdown, { width: '100%' }]}
|
|
|
+ placeholderStyle={[ModalStyles.placeholderStyle]}
|
|
|
+ selectedTextStyle={ModalStyles.selectedTextStyle}
|
|
|
+ containerStyle={[ModalStyles.dropdownContent, {}]}
|
|
|
+ data={series}
|
|
|
+ labelField="label"
|
|
|
+ valueField="value"
|
|
|
+ value={selectedSeries}
|
|
|
+ placeholder="Select series"
|
|
|
+ dropdownPosition="top"
|
|
|
+ activeColor="#E7E7E7"
|
|
|
+ flatListProps={{ initialNumToRender: 30, maxToRenderPerBatch: 10 }}
|
|
|
+ onChange={(item) => {
|
|
|
+ setSelectedSeries(item);
|
|
|
+ }}
|
|
|
+ renderItem={(item) => (
|
|
|
+ <View style={styles.multiOption}>
|
|
|
+ <View style={[styles.row, { gap: 8, flex: 1 }]}>
|
|
|
+ <Image source={{ uri: API_HOST + item.icon }} width={20} height={20} />
|
|
|
+ <Text style={styles.optionText}>{item.label}</Text>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {selectedSeries.includes(item.value) && (
|
|
|
+ <CheckSvg fill={Colors.DARK_BLUE} height={8} />
|
|
|
+ )}
|
|
|
+ </View>
|
|
|
+ )}
|
|
|
+ renderSelectedItem={(item, unSelect) => {
|
|
|
+ return null;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ <View style={{ gap: 16 }}>
|
|
|
+ <Button
|
|
|
+ children="Filter"
|
|
|
+ onPress={() => {
|
|
|
+ setSeriesFilter &&
|
|
|
+ setSeriesFilter({
|
|
|
+ visible: seriesVisible,
|
|
|
+ groups: selectedSeries,
|
|
|
+ applied: true,
|
|
|
+ status: selectedSeriesFilter
|
|
|
+ });
|
|
|
+ setIsFilterVisible(false);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ children="Clear"
|
|
|
+ onPress={() => {
|
|
|
+ setSelectedSeries(series?.map((item) => item.value));
|
|
|
+ setSelectedSeriesFilter(-1);
|
|
|
+ setSeriesVisible(true);
|
|
|
+ setSeriesFilter &&
|
|
|
+ setSeriesFilter({ visible: true, groups: [], applied: false, status: -1 });
|
|
|
+ }}
|
|
|
+ variant={ButtonVariants.OPACITY}
|
|
|
+ containerStyles={styles.closeBtn}
|
|
|
+ textStyles={{ color: Colors.DARK_BLUE }}
|
|
|
+ />
|
|
|
</View>
|
|
|
</View>
|
|
|
- </Modal>
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <ReactModal
|
|
|
+ isVisible={isFilterVisible}
|
|
|
+ onBackdropPress={() => setIsFilterVisible(false)}
|
|
|
+ onBackButtonPress={() => setIsFilterVisible(false)}
|
|
|
+ style={styles.modal}
|
|
|
+ statusBarTranslucent={true}
|
|
|
+ presentationStyle="overFullScreen"
|
|
|
+ >
|
|
|
+ <View style={[styles.modalContainer, { height: 400 }]}>
|
|
|
+ <TabView
|
|
|
+ navigationState={{ index, routes }}
|
|
|
+ renderScene={renderScene}
|
|
|
+ onIndexChange={setIndex}
|
|
|
+ lazy={true}
|
|
|
+ swipeEnabled={!isPublicView}
|
|
|
+ renderTabBar={(props) =>
|
|
|
+ !isPublicView ? (
|
|
|
+ <TabBar
|
|
|
+ {...props}
|
|
|
+ indicatorStyle={{ backgroundColor: Colors.DARK_BLUE }}
|
|
|
+ style={styles.tabBar}
|
|
|
+ tabStyle={styles.tabStyle}
|
|
|
+ pressColor={'transparent'}
|
|
|
+ renderLabel={({ route, focused }) => (
|
|
|
+ <Text
|
|
|
+ style={[
|
|
|
+ styles.tabLabel,
|
|
|
+ { color: Colors.DARK_BLUE, opacity: focused ? 1 : 0.4 }
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ {route.title}
|
|
|
+ </Text>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ ) : null
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </ReactModal>
|
|
|
);
|
|
|
};
|
|
|
|