Viktoriia 1 год назад
Родитель
Сommit
b3a25aa979

+ 3 - 0
src/modules/api/ranking/queries/index.ts

@@ -4,3 +4,6 @@ export * from './use-post-get-lpi';
 export * from './use-post-get-in-history';
 export * from './use-post-get-in-memoriam';
 export * from './use-post-get-un-masters';
+export * from './use-post-get-countries-ranking';
+export * from './use-post-get-countries-ranking-lpi';
+export * from './use-post-get-countries-ranking-memoriam';

+ 16 - 0
src/modules/api/ranking/queries/use-post-get-countries-ranking-lpi.tsx

@@ -0,0 +1,16 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { rankingQueryKeys } from '../ranking-query-keys';
+import { type PostGetCountriesRanking, rankingApi } from '../ranking-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetCountriesRankingLPI = () => {
+  return useQuery<PostGetCountriesRanking, BaseAxiosError>({
+    queryKey: rankingQueryKeys.getCountriesRankingLPI(),
+    queryFn: async () => {
+      const response = await rankingApi.getCountriesRankingLPI();
+      return response.data;
+    }
+  });
+};

+ 16 - 0
src/modules/api/ranking/queries/use-post-get-countries-ranking-memoriam.tsx

@@ -0,0 +1,16 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { rankingQueryKeys } from '../ranking-query-keys';
+import { type PostGetCountriesRanking, rankingApi } from '../ranking-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetCountriesRankingMemoriam = () => {
+  return useQuery<PostGetCountriesRanking, BaseAxiosError>({
+    queryKey: rankingQueryKeys.getCountriesRankingMemoriam(),
+    queryFn: async () => {
+      const response = await rankingApi.getCountriesRankingMemoriam();
+      return response.data;
+    }
+  });
+};

+ 16 - 0
src/modules/api/ranking/queries/use-post-get-countries-ranking.tsx

@@ -0,0 +1,16 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { rankingQueryKeys } from '../ranking-query-keys';
+import { type PostGetCountriesRanking, rankingApi } from '../ranking-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const usePostGetCountriesRanking = () => {
+  return useQuery<PostGetCountriesRanking, BaseAxiosError>({
+    queryKey: rankingQueryKeys.getCountriesRanking(),
+    queryFn: async () => {
+      const response = await rankingApi.getCountriesRanking();
+      return response.data;
+    }
+  });
+};

+ 10 - 2
src/modules/api/ranking/ranking-api.tsx

@@ -94,7 +94,7 @@ export interface Masters {
 
 export interface YearUNType extends ResponseType {
   data: {
-    year: number,
+    year: number;
     masters: Masters[];
   }[];
 }
@@ -114,6 +114,10 @@ export interface PostGetUNType extends ResponseType {
   };
 }
 
+export interface PostGetCountriesRanking extends ResponseType {
+  data: { two: string; name: string }[];
+}
+
 export const rankingApi = {
   getLimitedRanking: () => request.postForm<PostGetRanking>(API.GET_LIMITED_RANKING),
   getFullRanking: () => request.postForm<PostGetRanking>(API.GET_FULL_RANKING),
@@ -122,5 +126,9 @@ export const rankingApi = {
   getInMemoriam: () => request.postForm<PostGetRanking>(API.GET_IN_MEMORIAM),
   getUNMastersTypes: () => request.postForm<PostGetUNTypes>(API.GET_UN_MASTERS_TYPES),
   getUNMastersType: (type: number) =>
-    request.postForm<PostGetUNType>(API.GET_UN_MASTERS_TYPE, { type })
+    request.postForm<PostGetUNType>(API.GET_UN_MASTERS_TYPE, { type }),
+  getCountriesRanking: () => request.get<PostGetCountriesRanking>(API.GET_COUNTRIES_RANKING),
+  getCountriesRankingLPI: () => request.get<PostGetCountriesRanking>(API.GET_COUNTRIES_RANKING_LPI),
+  getCountriesRankingMemoriam: () =>
+    request.get<PostGetCountriesRanking>(API.GET_COUNTRIES_RANKING_MEMORIAM)
 };

+ 3 - 0
src/modules/api/ranking/ranking-query-keys.tsx

@@ -6,4 +6,7 @@ export const rankingQueryKeys = {
   getInMemoriam: () => ['getInMemoriam'] as const,
   getUNMastersTypes: () => ['getUNMastersTypes'] as const,
   getUNMastersType: (type: number) => ['getUNMastersType', { type }] as const,
+  getCountriesRanking: () => ['getCountriesRanking'] as const,
+  getCountriesRankingLPI: () => ['getCountriesRankingLPI'] as const,
+  getCountriesRankingMemoriam: () => ['getCountriesRankingMemoriam'] as const
 };

+ 137 - 0
src/screens/InAppScreens/TravellersScreen/Components/FilterModal.tsx

@@ -0,0 +1,137 @@
+import React, { FC, useState } from 'react';
+import Modal from 'react-native-modal';
+import { Dropdown } from 'react-native-searchable-dropdown-kj';
+import { Text, TouchableOpacity, View } from 'react-native';
+
+import { getOnlineStatus } from '../../../../storage';
+
+import { ModalStyles } from './styles';
+import { Colors } from '../../../../theme';
+
+import { Button } from '../../../../components';
+import { ButtonVariants } from '../../../../types/components';
+
+import { dataAge, dataRanking } from '../utils';
+
+import CloseIcon from '../../../../../assets/icons/close.svg';
+import {
+  filterAgeType,
+  FilterButtonProps,
+  filterCountryType,
+  filterRankingType,
+  ModalProps
+} from '../utils/types';
+import FilterIcon from '../../../../../assets/icons/filter.svg';
+
+export const FilterModal: FC<ModalProps> = ({
+  isModalVisible,
+  setModalVisible,
+  countriesData,
+  applyFilter
+}) => {
+  const [filterAge, setFilterAge] = useState<filterAgeType>(null);
+  const [filterRanking, setFilterRanking] = useState<filterRankingType>(null);
+  const [filterCountry, setFilterCountry] = useState<filterCountryType>(null);
+
+  return (
+    <Modal isVisible={isModalVisible}>
+      <View style={{ height: 270, backgroundColor: 'white', borderRadius: 15 }}>
+        <View style={{ marginLeft: '5%', marginRight: '5%', marginTop: '5%' }}>
+          <View style={{ alignSelf: 'flex-end' }}>
+            <TouchableOpacity onPress={() => setModalVisible(!isModalVisible)}>
+              <CloseIcon />
+            </TouchableOpacity>
+          </View>
+          <View style={{ display: 'flex', alignItems: 'center' }}>
+            <Text style={{ color: Colors.DARK_BLUE, fontSize: 20, fontWeight: '700' }}>Filter</Text>
+            <View style={ModalStyles.ageAndRankingWrapper}>
+              <Dropdown
+                style={ModalStyles.dropdown}
+                placeholderStyle={ModalStyles.placeholderStyle}
+                selectedTextStyle={ModalStyles.selectedTextStyle}
+                data={dataAge}
+                disable={!getOnlineStatus()}
+                labelField="label"
+                valueField="value"
+                value={filterAge?.value}
+                placeholder="Select age"
+                onChange={(item) => {
+                  setFilterAge(item);
+                }}
+              />
+              <Dropdown
+                style={ModalStyles.dropdown}
+                placeholderStyle={ModalStyles.placeholderStyle}
+                selectedTextStyle={ModalStyles.selectedTextStyle}
+                data={dataRanking}
+                labelField="label"
+                valueField="value"
+                value={filterRanking?.value}
+                placeholder="Select ranking"
+                onChange={(item) => {
+                  setFilterRanking(item);
+                }}
+              />
+            </View>
+            <Dropdown
+              style={[ModalStyles.dropdown, { width: '100%', marginTop: 15 }]}
+              placeholderStyle={ModalStyles.placeholderStyle}
+              selectedTextStyle={ModalStyles.selectedTextStyle}
+              data={countriesData}
+              disable={!getOnlineStatus()}
+              labelField="name"
+              valueField="two"
+              value={filterCountry?.two}
+              placeholder="Select country"
+              onChange={(item) => {
+                setFilterCountry(item);
+              }}
+            />
+            <View style={ModalStyles.buttonsWrapper}>
+              <Button
+                variant={ButtonVariants.OPACITY}
+                containerStyles={{
+                  borderColor: Colors.DARK_BLUE,
+                  backgroundColor: 'white',
+                  width: '45%'
+                }}
+                textStyles={{
+                  color: Colors.DARK_BLUE
+                }}
+                onPress={() => {
+                  setFilterAge(null);
+                  setFilterRanking(null);
+                  setFilterCountry(null);
+                }}
+                children={'Clear'}
+              />
+              <Button
+                variant={ButtonVariants.FILL}
+                containerStyles={{
+                  borderColor: Colors.DARK_BLUE,
+                  backgroundColor: Colors.DARK_BLUE,
+                  width: '45%'
+                }}
+                textStyles={{
+                  color: Colors.WHITE
+                }}
+                onPress={() => {
+                  applyFilter(filterAge, filterRanking, filterCountry);
+                }}
+                children={'Filter'}
+              />
+            </View>
+          </View>
+        </View>
+      </View>
+    </Modal>
+  );
+};
+
+export const FilterButton: FC<FilterButtonProps> = ({ onPress }) => {
+  return (
+    <TouchableOpacity style={{ padding: 5 }} onPress={onPress}>
+      <FilterIcon />
+    </TouchableOpacity>
+  );
+};

+ 33 - 0
src/screens/InAppScreens/TravellersScreen/Components/styles.ts

@@ -171,3 +171,36 @@ export const HorizontalSelectStyles = StyleSheet.create({
     backgroundColor: Colors.ORANGE
   }
 });
+
+export const ModalStyles = StyleSheet.create({
+  dropdown: {
+    width: '47%',
+    height: 40,
+    backgroundColor: '#F4F4F4',
+    borderRadius: 4,
+    paddingHorizontal: 8
+  },
+  placeholderStyle: {
+    fontSize: 16,
+    color: Colors.DARK_BLUE
+  },
+  selectedTextStyle: {
+    fontSize: 16,
+    color: Colors.DARK_BLUE
+  },
+  ageAndRankingWrapper: {
+    width: '100%',
+    display: 'flex',
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'space-between',
+    marginTop: 20
+  },
+  buttonsWrapper: {
+    width: '100%',
+    display: 'flex',
+    justifyContent: 'space-between',
+    flexDirection: 'row',
+    marginTop: 15
+  }
+});

+ 35 - 5
src/screens/InAppScreens/TravellersScreen/InHistoryScreen/index.tsx

@@ -6,12 +6,21 @@ import { Header, PageWrapper, Loading } from '../../../../components';
 import { storage, StoreType } from '../../../../storage';
 
 import { Profile } from '../Components/Profile';
+import { FilterButton, FilterModal } from '../Components/FilterModal';
+
+import { applyModalSort, dataRanking } from '../utils';
+import { RankingDropdown } from '../utils/types';
 
 import type { Ranking } from '..';
+
 const InHistoryScreen = () => {
   const [historyRanking, setHistoryRanking] = useState<Ranking[]>([]);
   const [isLoading, setIsLoading] = useState(true);
 
+  const [filteredData, setFilteredData] = useState<Ranking[]>([]);
+  const [isModalActive, setIsModalActive] = useState(false);
+  const [confirmedValueRanking, setConfirmedValueRanking] = useState<RankingDropdown | null>();
+
   useFocusEffect(
     useCallback(() => {
       const fetchRanking = async () => {
@@ -30,13 +39,29 @@ const InHistoryScreen = () => {
 
   return (
     <PageWrapper>
+      <FilterModal
+        isModalVisible={isModalActive}
+        setModalVisible={(value) => setIsModalActive(value)}
+        applyFilter={(filterAge, filterRanking, filterCountry) => {
+          setConfirmedValueRanking(filterRanking);
+          setFilteredData(applyModalSort(historyRanking, filterAge, filterRanking, filterCountry));
+          setIsModalActive(false);
+        }}
+        countriesData={[]}
+      />
+
+      <Header
+        label="In History"
+        rightElement={<FilterButton onPress={() => setIsModalActive(!isModalActive)} />}
+      />
+
       <FlatList
         showsVerticalScrollIndicator={false}
-        ListHeaderComponent={<Header label="In History" />}
-        data={historyRanking}
+        data={filteredData.length > 0 ? filteredData : historyRanking}
         keyExtractor={(item) => item.user_id.toString()}
         renderItem={({ item, index }) => (
           <Profile
+            userId={item.user_id}
             key={index}
             index={index}
             first_name={item.first_name}
@@ -45,24 +70,29 @@ const InHistoryScreen = () => {
             date_of_birth={item.age}
             homebase_flag={item.flag1}
             homebase2_flag={item.flag2}
-            tbt_score={item.score_tbt}
             score={[
               item.score_nm,
               item.score_dare,
               item.score_un,
               item.score_unp,
               item.score_tcc,
+              item.score_deep,
               item.score_yes,
               item.score_slow,
               item.score_whs,
               item.score_kye
             ]}
-            auth={item.auth}
+            active_score={
+              confirmedValueRanking ? confirmedValueRanking.value - 1 : dataRanking[0].value - 1
+            }
+            tbt_score={item.score_tbt}
+            tbt_rank={item.rank_tbt}
+            badge_tbt={item.badge_tbt}
             badge_1281={item.badge_1281}
             badge_un={item.badge_un}
+            auth={item.auth}
           />
         )}
-        onEndReachedThreshold={0.1}
       />
     </PageWrapper>
   );

+ 33 - 3
src/screens/InAppScreens/TravellersScreen/InMemoriamScreen/index.tsx

@@ -1,11 +1,16 @@
 import React, { useCallback, useState } from 'react';
 import { FlatList } from 'react-native';
 import { useFocusEffect } from '@react-navigation/native';
+import { usePostGetCountriesRankingMemoriam } from '@api/ranking';
 
 import { Header, Loading, PageWrapper } from '../../../../components';
 import { storage, StoreType } from '../../../../storage';
 
 import { Profile } from '../Components/Profile';
+import { FilterButton, FilterModal } from '../Components/FilterModal';
+
+import { applyModalSort, dataRanking } from '../utils';
+import { RankingDropdown } from '../utils/types';
 
 import type { Ranking } from '..';
 
@@ -13,6 +18,12 @@ const InMemoriamScreen = () => {
   const [memoriamRanking, setMemoriamRanking] = useState<Ranking[]>([]);
   const [isLoading, setIsLoading] = useState(true);
 
+  const [filteredData, setFilteredData] = useState<Ranking[]>([]);
+  const [isModalActive, setIsModalActive] = useState(false);
+  const [confirmedValueRanking, setConfirmedValueRanking] = useState<RankingDropdown | null>();
+
+  const { data: inMemoriamCountries } = usePostGetCountriesRankingMemoriam();
+
   useFocusEffect(
     useCallback(() => {
       const fetchRanking = async () => {
@@ -31,13 +42,29 @@ const InMemoriamScreen = () => {
 
   return (
     <PageWrapper>
+      <FilterModal
+        isModalVisible={isModalActive}
+        setModalVisible={(value) => setIsModalActive(value)}
+        applyFilter={(filterAge, filterRanking, filterCountry) => {
+          setConfirmedValueRanking(filterRanking);
+          setFilteredData(applyModalSort(memoriamRanking, filterAge, filterRanking, filterCountry));
+          setIsModalActive(false);
+        }}
+        countriesData={inMemoriamCountries ? inMemoriamCountries.data : []}
+      />
+
+      <Header
+        label="In Memoriam"
+        rightElement={<FilterButton onPress={() => setIsModalActive(!isModalActive)} />}
+      />
+
       <FlatList
         showsVerticalScrollIndicator={false}
-        data={memoriamRanking}
-        ListHeaderComponent={<Header label="In Memoriam" />}
+        data={filteredData.length > 0 ? filteredData : memoriamRanking}
         keyExtractor={(item) => item.user_id.toString()}
         renderItem={({ item, index }) => (
           <Profile
+            userId={item.user_id}
             key={index}
             index={index}
             first_name={item.first_name}
@@ -52,11 +79,15 @@ const InMemoriamScreen = () => {
               item.score_un,
               item.score_unp,
               item.score_tcc,
+              item.score_deep,
               item.score_yes,
               item.score_slow,
               item.score_whs,
               item.score_kye
             ]}
+            active_score={
+              confirmedValueRanking ? confirmedValueRanking.value - 1 : dataRanking[0].value - 1
+            }
             tbt_score={item.score_tbt}
             tbt_rank={item.rank_tbt}
             badge_tbt={item.badge_tbt}
@@ -65,7 +96,6 @@ const InMemoriamScreen = () => {
             auth={item.auth}
           />
         )}
-        onEndReachedThreshold={0.1}
       />
     </PageWrapper>
   );

+ 33 - 2
src/screens/InAppScreens/TravellersScreen/LPIRankingScreen/index.tsx

@@ -1,11 +1,16 @@
 import React, { useCallback, useState } from 'react';
 import { FlatList } from 'react-native';
 import { useFocusEffect } from '@react-navigation/native';
+import { usePostGetCountriesRankingLPI } from '@api/ranking';
 
 import { Header, Loading, PageWrapper } from '../../../../components';
 import { storage, StoreType } from '../../../../storage';
 
 import { Profile } from '../Components/Profile';
+import { FilterButton, FilterModal } from '../Components/FilterModal';
+
+import { applyModalSort, dataRanking } from '../utils';
+import { RankingDropdown } from '../utils/types';
 
 import type { Ranking } from '..';
 
@@ -13,6 +18,12 @@ const LPIRankingScreen = () => {
   const [LPIRanking, setLPIRanking] = useState<Ranking[]>([]);
   const [isLoading, setIsLoading] = useState(true);
 
+  const [filteredData, setFilteredData] = useState<Ranking[]>([]);
+  const [isModalActive, setIsModalActive] = useState(false);
+  const [confirmedValueRanking, setConfirmedValueRanking] = useState<RankingDropdown | null>();
+
+  const { data: lpiCountries } = usePostGetCountriesRankingLPI();
+
   useFocusEffect(
     useCallback(() => {
       const fetchRanking = async () => {
@@ -29,14 +40,30 @@ const LPIRankingScreen = () => {
 
   return (
     <PageWrapper>
+      <FilterModal
+        isModalVisible={isModalActive}
+        setModalVisible={(value) => setIsModalActive(value)}
+        applyFilter={(filterAge, filterRanking, filterCountry) => {
+          setConfirmedValueRanking(filterRanking);
+          setFilteredData(applyModalSort(LPIRanking, filterAge, filterRanking, filterCountry));
+          setIsModalActive(false);
+        }}
+        countriesData={lpiCountries ? lpiCountries.data : []}
+      />
+
+      <Header
+        label="LPI Ranking"
+        rightElement={<FilterButton onPress={() => setIsModalActive(!isModalActive)} />}
+      />
+
       <FlatList
-        data={LPIRanking}
+        data={filteredData.length > 0 ? filteredData : LPIRanking}
         showsVerticalScrollIndicator={false}
-        ListHeaderComponent={<Header label="LPI Ranking" />}
         keyExtractor={(item) => item.user_id.toString()}
         onEndReachedThreshold={0.1}
         renderItem={({ item, index }) => (
           <Profile
+            userId={item.user_id}
             key={index}
             index={index}
             first_name={item.first_name}
@@ -51,11 +78,15 @@ const LPIRankingScreen = () => {
               item.score_un,
               item.score_unp,
               item.score_tcc,
+              item.score_deep,
               item.score_yes,
               item.score_slow,
               item.score_whs,
               item.score_kye
             ]}
+            active_score={
+              confirmedValueRanking ? confirmedValueRanking.value - 1 : dataRanking[0].value - 1
+            }
             tbt_score={item.score_tbt}
             tbt_rank={item.rank_tbt}
             badge_tbt={item.badge_tbt}

+ 27 - 172
src/screens/InAppScreens/TravellersScreen/MasterRankingScreen/index.tsx

@@ -1,43 +1,30 @@
 import React, { useCallback, useState } from 'react';
 import { useFocusEffect } from '@react-navigation/native';
-import { FlatList, Text, TouchableOpacity, View } from 'react-native';
-import { Dropdown } from 'react-native-searchable-dropdown-kj';
-import Modal from 'react-native-modal';
+import { FlatList } from 'react-native';
 
-import { fetchFullRanking } from '@api/ranking';
+import { fetchFullRanking, usePostGetCountriesRanking } from '@api/ranking';
 
-import { styles } from './styles';
-import { Colors } from '../../../../theme';
-
-import { dataAge, dataRanking } from './values';
-
-import { Button, Header, Loading, PageWrapper } from '../../../../components';
+import { Header, Loading, PageWrapper } from '../../../../components';
 import { getOnlineStatus, storage, StoreType } from '../../../../storage';
 
 import { Profile } from '../Components/Profile';
+import { FilterModal, FilterButton } from '../Components/FilterModal';
 
-import { ButtonVariants } from '../../../../types/components';
-
-import FilterIcon from '../../../../../assets/icons/filter.svg';
-import CloseIcon from '../../../../../assets/icons/close.svg';
+import { applyModalSort, dataRanking } from '../utils';
+import type { RankingDropdown } from '../utils/types';
 
 import type { Ranking } from '..';
 
-type RankingDropdown = { value: number; label: string };
-
-const RankingDropdownObject = { value: 1, label: 'NM' };
-
 const MasterRankingScreen = () => {
-  const [masterRanking, setMasterRanking] = useState<Ranking[]>([]);
   const { mutateAsync } = fetchFullRanking();
+  const { data: masterCountries } = usePostGetCountriesRanking();
+
+  const [masterRanking, setMasterRanking] = useState<Ranking[]>([]);
   const [isLoading, setIsLoading] = useState(true);
-  const [isModalVisible, setModalVisible] = useState(false);
 
-  const [valueAge, setValueAge] = useState<{ value: string; label: string } | null>();
-  const [valueRanking, setValueRanking] = useState<RankingDropdown>(RankingDropdownObject);
-  const [confirmedValueRanking, setConfirmedValueRanking] =
-    useState<RankingDropdown>(RankingDropdownObject);
-  const [valueCountry, setValueCountry] = useState(null);
+  const [filteredData, setFilteredData] = useState<Ranking[]>([]);
+  const [isModalVisible, setModalVisible] = useState(false);
+  const [confirmedValueRanking, setConfirmedValueRanking] = useState<RankingDropdown | null>();
 
   useFocusEffect(
     useCallback(() => {
@@ -65,161 +52,27 @@ const MasterRankingScreen = () => {
     }
   };
 
-  const applySort = () => {
-    setConfirmedValueRanking(valueRanking);
-
-    switch (valueRanking?.label) {
-      case 'NM':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_nm - a.score_nm));
-        break;
-      case 'DARE':
-        setMasterRanking(
-          masterRanking.sort((a: Ranking, b: Ranking) => b.score_dare - a.score_dare)
-        );
-        break;
-      case 'UN':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_un - a.score_un));
-        break;
-      case 'UN+':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_unp - a.score_unp));
-        break;
-      case 'TCC':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_tcc - a.score_tcc));
-        break;
-      case 'DEEP':
-        //TODO: Crash
-        setMasterRanking(
-          masterRanking.sort((a: Ranking, b: Ranking) => b.score_deep - a.score_deep)
-        );
-        break;
-      case 'YES':
-        const validUsers = masterRanking.filter((user) => user.score_yes !== 10000);
-        setMasterRanking(validUsers.sort((a: Ranking, b: Ranking) => a.score_yes - b.score_yes));
-        break;
-      case 'SLOW':
-        const valiidUsers = masterRanking.filter(
-          (user) => user.score_slow < 4500 && user.score_slow > 0
-        );
-        setMasterRanking(valiidUsers.sort((a: Ranking, b: Ranking) => b.score_slow - a.score_slow));
-        break;
-      case 'WHS':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_whs - a.score_whs));
-        break;
-      case 'KYE':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_kye - a.score_kye));
-        break;
-      case 'TBT':
-        setMasterRanking(masterRanking.sort((a: Ranking, b: Ranking) => b.score_tbt - a.score_tbt));
-        break;
-    }
-  };
-
   return (
     <PageWrapper>
-      <Modal isVisible={isModalVisible}>
-        <View style={{ height: 270, backgroundColor: 'white', borderRadius: 15 }}>
-          <View style={{ marginLeft: '5%', marginRight: '5%', marginTop: '5%' }}>
-            <View style={{ alignSelf: 'flex-end' }}>
-              <TouchableOpacity onPress={() => setModalVisible(!isModalVisible)}>
-                <CloseIcon />
-              </TouchableOpacity>
-            </View>
-            <View style={{ display: 'flex', alignItems: 'center' }}>
-              <Text style={{ color: Colors.DARK_BLUE, fontSize: 20, fontWeight: '700' }}>
-                Filter
-              </Text>
-              <View style={styles.ageAndRankingWrapper}>
-                <Dropdown
-                  style={styles.dropdown}
-                  placeholderStyle={styles.placeholderStyle}
-                  selectedTextStyle={styles.selectedTextStyle}
-                  data={dataAge}
-                  labelField="label"
-                  valueField="value"
-                  placeholder="Select age"
-                  value={valueAge?.value}
-                  onChange={(item) => {
-                    setValueAge(item);
-                  }}
-                />
-                <Dropdown
-                  style={styles.dropdown}
-                  placeholderStyle={styles.placeholderStyle}
-                  selectedTextStyle={styles.selectedTextStyle}
-                  data={dataRanking}
-                  labelField="label"
-                  valueField="value"
-                  placeholder="Select ranking"
-                  value={valueRanking.value}
-                  onChange={(item) => {
-                    setValueRanking(item);
-                  }}
-                />
-              </View>
-              <Dropdown
-                style={[styles.dropdown, { width: '100%', marginTop: 15 }]}
-                placeholderStyle={styles.placeholderStyle}
-                selectedTextStyle={styles.selectedTextStyle}
-                data={[]}
-                labelField="label"
-                valueField="value"
-                placeholder="Select country"
-                value={valueRanking?.value}
-                onChange={(item) => {
-                  //todo: Country
-                }}
-              />
-              <View style={styles.buttonsWrapper}>
-                <Button
-                  variant={ButtonVariants.OPACITY}
-                  containerStyles={{
-                    borderColor: Colors.DARK_BLUE,
-                    backgroundColor: 'white',
-                    width: '45%'
-                  }}
-                  textStyles={{
-                    color: Colors.DARK_BLUE
-                  }}
-                  onPress={() => {
-                    setValueAge(null);
-                    setValueRanking(RankingDropdownObject);
-                  }}
-                  children={'Clear'}
-                />
-                <Button
-                  variant={ButtonVariants.FILL}
-                  containerStyles={{
-                    borderColor: Colors.DARK_BLUE,
-                    backgroundColor: Colors.DARK_BLUE,
-                    width: '45%'
-                  }}
-                  textStyles={{
-                    color: Colors.WHITE
-                  }}
-                  onPress={() => {
-                    setModalVisible(!isModalVisible);
-                    applySort();
-                  }}
-                  children={'Filter'}
-                />
-              </View>
-            </View>
-          </View>
-        </View>
-      </Modal>
+      <FilterModal
+        isModalVisible={isModalVisible}
+        setModalVisible={(value) => setModalVisible(value)}
+        applyFilter={(filterAge, filterRanking, filterCountry) => {
+          setConfirmedValueRanking(filterRanking);
+          setFilteredData(applyModalSort(masterRanking, filterAge, filterRanking, filterCountry));
+          setModalVisible(false);
+        }}
+        countriesData={masterCountries ? masterCountries.data : []}
+      />
 
       <Header
         label="Master Ranking"
-        rightElement={
-          <TouchableOpacity style={{ padding: 5 }} onPress={() => setModalVisible(!isModalVisible)}>
-            <FilterIcon />
-          </TouchableOpacity>
-        }
+        rightElement={<FilterButton onPress={() => setModalVisible(!isModalVisible)} />}
       />
 
       <FlatList
         showsVerticalScrollIndicator={false}
-        data={masterRanking}
+        data={filteredData.length != 0 ? filteredData : masterRanking}
         keyExtractor={(item) => item.user_id.toString()}
         renderItem={({ item, index }) => (
           <Profile
@@ -244,8 +97,10 @@ const MasterRankingScreen = () => {
               item.score_whs,
               item.score_kye
             ]}
+            active_score={
+              confirmedValueRanking ? confirmedValueRanking.value - 1 : dataRanking[0].value - 1
+            }
             tbt_score={item.score_tbt}
-            active_score={confirmedValueRanking.value - 1}
             tbt_rank={item.rank_tbt}
             badge_tbt={item.badge_tbt}
             badge_1281={item.badge_1281}

+ 0 - 35
src/screens/InAppScreens/TravellersScreen/MasterRankingScreen/styles.ts

@@ -1,35 +0,0 @@
-import { StyleSheet } from 'react-native';
-import { Colors } from '../../../../theme';
-
-export const styles = StyleSheet.create({
-  dropdown: {
-    width: '47%',
-    height: 40,
-    backgroundColor: '#F4F4F4',
-    borderRadius: 4,
-    paddingHorizontal: 8
-  },
-  placeholderStyle: {
-    fontSize: 16,
-    color: Colors.DARK_BLUE
-  },
-  selectedTextStyle: {
-    fontSize: 16,
-    color: Colors.DARK_BLUE
-  },
-  ageAndRankingWrapper: {
-    width: '100%',
-    display: 'flex',
-    flexDirection: 'row',
-    alignItems: 'center',
-    justifyContent: 'space-between',
-    marginTop: 20
-  },
-  buttonsWrapper: {
-    width: '100%',
-    display: 'flex',
-    justifyContent: 'space-between',
-    flexDirection: 'row',
-    marginTop: 15
-  }
-});

+ 2 - 0
src/screens/InAppScreens/TravellersScreen/utils/index.ts

@@ -0,0 +1,2 @@
+export * from './sort';
+export * from './values';

+ 90 - 0
src/screens/InAppScreens/TravellersScreen/utils/sort.ts

@@ -0,0 +1,90 @@
+import { Ranking } from '..';
+import { filterAgeType, filterCountryType, filterRankingType } from './types';
+
+export const applyModalSort = (
+  allRanking: Ranking[],
+  age: filterAgeType,
+  ranking: filterRankingType,
+  country: filterCountryType
+) => {
+  let filteredLocalData = allRanking;
+
+  if (age) {
+    filteredLocalData = filteredLocalData.filter(
+      (user) => user.age >= age.min && user.age <= age.max
+    );
+  }
+
+  if (country) {
+    filteredLocalData = filteredLocalData.filter(
+      (user) => user.country === country.two.toLowerCase()
+    );
+  }
+
+  if (ranking) {
+    switch (ranking?.label) {
+      case 'NM':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_nm - a.score_nm
+        );
+        break;
+      case 'DARE':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_dare - a.score_dare
+        );
+        break;
+      case 'UN':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_un - a.score_un
+        );
+        break;
+      case 'UN+':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_unp - a.score_unp
+        );
+        break;
+      case 'TCC':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_tcc - a.score_tcc
+        );
+        break;
+      case 'DEEP':
+        //TODO: Crash
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_deep - a.score_deep
+        );
+        break;
+      case 'YES':
+        const YESFilteredUsers = filteredLocalData.filter((user) => user.score_yes !== 10000);
+        filteredLocalData = YESFilteredUsers.sort(
+          (a: Ranking, b: Ranking) => a.score_yes - b.score_yes
+        );
+        break;
+      case 'SLOW':
+        const SLOWFilteredUsers = allRanking.filter(
+          (user) => user.score_slow < 4500 && user.score_slow > 0
+        );
+        filteredLocalData = SLOWFilteredUsers.sort(
+          (a: Ranking, b: Ranking) => b.score_slow - a.score_slow
+        );
+        break;
+      case 'WHS':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_whs - a.score_whs
+        );
+        break;
+      case 'KYE':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_kye - a.score_kye
+        );
+        break;
+      case 'TBT':
+        filteredLocalData = filteredLocalData.sort(
+          (a: Ranking, b: Ranking) => b.score_tbt - a.score_tbt
+        );
+        break;
+    }
+  }
+
+  return filteredLocalData;
+};

+ 27 - 0
src/screens/InAppScreens/TravellersScreen/utils/types.ts

@@ -0,0 +1,27 @@
+export type filterAgeType = {
+  value: string;
+  label: string;
+  min: number;
+  max: number;
+} | null;
+
+export type filterRankingType = { value: number; label: string } | null;
+
+export type filterCountryType = { two: string; name: string } | null;
+
+export type RankingDropdown = { value: number; label: string };
+
+export type ModalProps = {
+  isModalVisible: boolean;
+  setModalVisible: (value: boolean) => void;
+  applyFilter: (
+    filterAge: filterAgeType,
+    filterRanking: filterRankingType,
+    filterCountry: filterCountryType
+  ) => void;
+  countriesData: { two: string; name: string }[];
+};
+
+export type FilterButtonProps = {
+  onPress: () => void;
+};

+ 7 - 7
src/screens/InAppScreens/TravellersScreen/MasterRankingScreen/values.ts → src/screens/InAppScreens/TravellersScreen/utils/values.ts

@@ -1,11 +1,11 @@
 export const dataAge = [
-  { label: 'until 19', value: '1' },
-  { label: '20 - 29', value: '2' },
-  { label: '30 - 39', value: '3' },
-  { label: '40 - 49', value: '4' },
-  { label: '50 - 59', value: '5' },
-  { label: '60 - 69', value: '6' },
-  { label: '70+', value: '7' }
+  { label: 'until 19', value: '1', min: 0, max: 19 },
+  { label: '20 - 29', value: '2', min: 20, max: 29 },
+  { label: '30 - 39', value: '3', min: 30, max: 39 },
+  { label: '40 - 49', value: '4', min: 40, max: 49 },
+  { label: '50 - 59', value: '5', min: 50, max: 59 },
+  { label: '60 - 69', value: '6', min: 60, max: 69 },
+  { label: '70+', value: '7', min: 70, max: 150 }
 ];
 
 export const dataRanking = [

+ 8 - 2
src/types/api.ts

@@ -33,7 +33,10 @@ export enum API_ENDPOINT {
   GET_LIST = 'get-list',
   GET_STATISTIC = 'get-stat',
   SERIES_GROUPS = 'get-series-groups',
-  SERIES_WITH_GROUP = 'get-series-with-group-app'
+  SERIES_WITH_GROUP = 'get-series-with-group-app',
+  GET_COUNTRIES_RANKING = 'get-countries-ranking',
+  GET_COUNTRIES_RANKING_LPI = 'get-countries-ranking-lpi',
+  GET_COUNTRIES_RANKING_MEMORIAM = 'get-countries-ranking-in-memoriam'
 }
 
 export enum API {
@@ -58,7 +61,10 @@ export enum API {
   GET_LIST = `${API_ROUTE.STATISTICS}/${API_ENDPOINT.GET_LIST}`,
   GET_STATISTIC = `${API_ROUTE.STATISTICS}/${API_ENDPOINT.GET_STATISTIC}`,
   SERIES_GROUPS = `${API_ROUTE.SERIES}/${API_ENDPOINT.SERIES_GROUPS}`,
-  SERIES_WITH_GROUP = `${API_ROUTE.SERIES}/${API_ENDPOINT.SERIES_WITH_GROUP}`
+  SERIES_WITH_GROUP = `${API_ROUTE.SERIES}/${API_ENDPOINT.SERIES_WITH_GROUP}`,
+  GET_COUNTRIES_RANKING = `${API_ROUTE.RANKING}/${API_ENDPOINT.GET_COUNTRIES_RANKING}`,
+  GET_COUNTRIES_RANKING_LPI = `${API_ROUTE.RANKING}/${API_ENDPOINT.GET_COUNTRIES_RANKING_LPI}`,
+  GET_COUNTRIES_RANKING_MEMORIAM = `${API_ROUTE.RANKING}/${API_ENDPOINT.GET_COUNTRIES_RANKING_MEMORIAM}`
 }
 
 export type BaseAxiosError = AxiosError;