ソースを参照

fix: components refactor | statistic end

Oleksandr Honcharov 1 年間 前
コミット
454e90f578

+ 2 - 5
Route.tsx

@@ -28,7 +28,6 @@ import InHistoryScreen from './src/screens/InAppScreens/TravellersScreen/InHisto
 import UNMastersScreen from './src/screens/InAppScreens/TravellersScreen/UNMasters';
 import StatisticsScreen from './src/screens/InAppScreens/TravellersScreen/StatisticsScreen';
 import StatisticsListScreen from './src/screens/InAppScreens/TravellersScreen/StatisticsListScreen';
-import NomadsStatistics from './src/screens/InAppScreens/TravellersScreen/NomadsStatistics';
 
 import SeriesScreen from 'src/screens/InAppScreens/TravelsScreen/Series';
 
@@ -46,6 +45,8 @@ const BottomTab = createBottomTabNavigator();
 
 SplashScreen.preventAutoHideAsync();
 
+//TODO: Fix types on Statistics
+
 const Route = () => {
   const token = storage.get('token', StoreType.STRING);
 
@@ -153,10 +154,6 @@ const Route = () => {
                     name={NAVIGATION_PAGES.STATISTICS_LIST_DATA}
                     component={StatisticsListScreen}
                   />
-                  <ScreenStack.Screen
-                    name={NAVIGATION_PAGES.NOMADS_STATISTICS}
-                    component={NomadsStatistics}
-                  />
                 </ScreenStack.Navigator>
               )}
             </BottomTab.Screen>

+ 10 - 0
src/database/statisticsService/index.ts

@@ -176,3 +176,13 @@ export interface Type9 {
   user_count: number;
   visited_countries: number;
 }
+
+export interface Type10 {
+  cnt: number;
+  flags: string[];
+  item_id: number;
+  item_name: string;
+  series_icon: string;
+  series_id: number;
+  series_name: string;
+}

+ 46 - 0
src/screens/InAppScreens/TravellersScreen/Components/SeriesItem.tsx

@@ -0,0 +1,46 @@
+import React, { FC } from 'react';
+import { Text, View } from 'react-native';
+import { Image } from 'expo-image';
+
+import { getFontSize } from '../../../../utils';
+import { API_HOST } from '../../../../constants';
+
+import { Colors } from '../../../../theme';
+
+import { ItemStyles } from './styles';
+
+type Props = {
+  name: string;
+  flags: string;
+  cnt: number | string;
+  index: number;
+};
+
+export const SeriesItem: FC<Props> = (data) => {
+  const flags: string[] = JSON.parse(data.flags);
+
+  return (
+    <View style={ItemStyles.wrapper}>
+      <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
+        {data.index + 1}
+      </Text>
+      <View style={ItemStyles.contentWrapper}>
+        <View style={{ width: '85%' }}>
+          {flags && (
+            <View style={ItemStyles.withFlagWrapper}>
+              {flags.map((flag, index) => (
+                <Image
+                  key={index}
+                  style={[ItemStyles.smallFlag, index !== 0 && { marginLeft: -5 }]}
+                  source={{ uri: API_HOST + '/img/flags_new/' + flag }}
+                />
+              ))}
+            </View>
+          )}
+          <Text style={ItemStyles.nameAndCnt}>{data.name}</Text>
+        </View>
+        <Text style={ItemStyles.nameAndCnt}>{data.cnt}</Text>
+      </View>
+    </View>
+  );
+};

+ 26 - 0
src/screens/InAppScreens/TravellersScreen/Components/StatisticItem.tsx

@@ -0,0 +1,26 @@
+import React, { FC } from 'react';
+import { Text, View } from 'react-native';
+import { Image } from 'expo-image';
+
+import { getFontSize } from '../../../../utils';
+import { API_HOST } from '../../../../constants';
+
+import { ItemStyles } from './styles';
+
+type Props = {
+  name: string;
+  flag: string;
+  cnt: number | string;
+  index: number;
+};
+
+export const StatisticItem: FC<Props> = (data) => (
+  <View style={ItemStyles.wrapper}>
+    <Text style={[ItemStyles.nameAndCnt, { fontSize: getFontSize(18) }]}>{data.index + 1}</Text>
+    <Image style={ItemStyles.bigFlag} source={{ uri: API_HOST + '/img/flags_new/' + data.flag }} />
+    <View style={ItemStyles.contentWrapper}>
+      <Text style={[{ width: '75%' }, ItemStyles.nameAndCnt]}>{data.name}</Text>
+      <Text style={ItemStyles.nameAndCnt}>{data.cnt}</Text>
+    </View>
+  </View>
+);

+ 122 - 0
src/screens/InAppScreens/TravellersScreen/Components/StatisticRouter.tsx

@@ -0,0 +1,122 @@
+import React, { FC } from 'react';
+import { Image } from 'expo-image';
+import { Text, View } from 'react-native';
+
+import { StatisticItem } from './StatisticItem';
+import { SeriesItem } from './SeriesItem';
+
+import { ListType } from '../../../../database/statisticsService';
+import {
+  isType1,
+  isType2,
+  isType4,
+  isType5,
+  isType6,
+  isType7,
+  isType8,
+  isType9,
+  isType10
+} from '../StatisticsListScreen/funcs';
+import { getFontSize } from '../../../../utils';
+import { API_HOST } from '../../../../constants';
+
+import { ItemStyles } from './styles';
+
+type Props = {
+  index: number;
+  item: ListType;
+  ranking: any;
+};
+
+export const RenderItem: FC<Props> = ({ item, index, ranking }) => {
+  if (isType1(item) || isType4(item) || isType5(item)) {
+    return (
+      <>
+        {'megaregion' in item && (
+          <View>
+            {item.megaregion !== ranking[index - 1]?.megaregion ? (
+              <Text style={[ItemStyles.nameAndCnt, ItemStyles.headerWrapper]}>
+                {item.megaregion as string}
+              </Text>
+            ) : null}
+          </View>
+        )}
+        <StatisticItem cnt={item.cnt} flag={item.flag} index={index} name={item.region_name} />
+      </>
+    );
+  } else if (isType6(item)) {
+    return (
+      <>
+        <View>
+          {item.country !== ranking[index - 1]?.country ? (
+            <Text style={[ItemStyles.nameAndCnt, ItemStyles.headerWrapper]}>{item.country}</Text>
+          ) : null}
+        </View>
+        <StatisticItem cnt={item.cnt} flag={item.region_flag} index={index} name={item.region} />
+      </>
+    );
+  } else if (isType2(item)) {
+    return (
+      <>
+        <View>
+          {item.mega_name !== ranking[index - 1]?.mega_name ? (
+            <Text style={[ItemStyles.nameAndCnt, ItemStyles.headerWrapper]}>
+              {item.mega_name as string}
+            </Text>
+          ) : null}
+        </View>
+        <StatisticItem name={item.dare_name} flag={item.dare_flag} cnt={item.cnt} index={index} />
+      </>
+    );
+  } else if (isType7(item)) {
+    return <StatisticItem name={item.country_name} flag={item.flag} cnt={item.cnt} index={index} />;
+  } else if (isType8(item)) {
+    return (
+      <>
+        <View>
+          {item.mega_name !== ranking[index - 1]?.mega_name ? (
+            <Text style={[ItemStyles.nameAndCnt, ItemStyles.headerWrapper]}>
+              {item.mega_name as string}
+            </Text>
+          ) : null}
+          <StatisticItem name={item.country} flag={item.flag} cnt={item.cnt} index={index} />
+        </View>
+      </>
+    );
+  } else if (isType9(item)) {
+    return <StatisticItem name={item.nation} flag={item.flag} cnt={item.score} index={index} />;
+  } else if (isType10(item)) {
+    return (
+      <>
+        {item.series_name !== ranking[index - 1]?.series_name ? (
+          <View style={ItemStyles.headerSeriesWrapper}>
+            <Image
+              key={index}
+              style={{ width: 20, height: 20, borderRadius: 10 }}
+              source={{ uri: API_HOST + '/static/img/series/' + item.series_icon }}
+            />
+            <Text style={[ItemStyles.nameAndCnt, { fontSize: getFontSize(14) }]}>
+              {item.series_name as string}
+            </Text>
+          </View>
+        ) : null}
+        <SeriesItem
+          name={item.item_name}
+          flags={item.flags as unknown as string}
+          cnt={item.cnt}
+          index={index}
+        />
+      </>
+    );
+  } else
+    return (
+      <>
+        <StatisticItem
+          name={item.nation ? item.nation : `${item.first_name} ${item.last_name}`}
+          flag={item.flag}
+          cnt={item.score ? item.score : item.cnt}
+          index={index}
+        />
+      </>
+    );
+};

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

@@ -204,3 +204,58 @@ export const ModalStyles = StyleSheet.create({
     marginTop: 15
   }
 });
+
+export const ItemStyles = StyleSheet.create({
+  wrapper: {
+    display: 'flex',
+    alignItems: 'center',
+    flexDirection: 'row',
+    flex: 1,
+    gap: 8
+  },
+  contentWrapper: {
+    flex: 1,
+    display: 'flex',
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+    alignItems: 'center'
+  },
+  bigFlag: {
+    width: 36,
+    height: 36,
+    borderRadius: 18
+  },
+  withFlagWrapper: {
+    display: 'flex',
+    flexDirection: 'row'
+  },
+  smallFlag: {
+    width: 20,
+    height: 20,
+    borderRadius: 10
+  },
+  nameAndCnt: {
+    color: Colors.DARK_BLUE,
+    fontWeight: '700'
+  },
+  headerWrapper: {
+    fontSize: getFontSize(14),
+    marginTop: 10,
+    marginBottom: 15,
+    textAlign: 'center'
+  },
+  headerSeriesWrapper: {
+    display: 'flex',
+    justifyContent: 'center',
+    alignItems: 'center',
+    flexDirection: 'row',
+    gap: 10,
+    marginTop: 10,
+    marginBottom: 15
+  },
+  comment: {
+    color: Colors.DARK_BLUE,
+    textAlign: 'center',
+    marginBottom: 15
+  }
+});

+ 0 - 119
src/screens/InAppScreens/TravellersScreen/NomadsStatistics/index.tsx

@@ -1,119 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { View, Text, FlatList, ScrollView } from 'react-native';
-import { Dropdown } from 'react-native-searchable-dropdown-kj';
-
-import { Header, Loading, PageWrapper } from '../../../../components';
-import { getStatistic, ListData, StatisticType } from '../../../../database/statisticsService';
-import { ModalStyles } from '../Components/styles';
-import { Colors } from '../../../../theme';
-import { getFontSize } from '../../../../utils';
-import { Image } from 'expo-image';
-import { API_HOST } from '../../../../constants';
-
-const NomadsStatistics = ({
-  route
-}: {
-  route: { params: { key: string; title: string; list?: ListData[] | undefined } };
-}) => {
-  const [data, setData] = useState([]);
-  const [selectedValue, setSelectedValue] = useState(route.params.sublist[0].list[0]);
-
-  const [statisticsData, setStatisticsData] = useState<null>();
-  function getDataByUrl(url1: string, url2: string | null) {
-    const data = getStatistic(url1, url2);
-    return JSON.parse(data as unknown as string) as unknown as StatisticType;
-  }
-
-  useEffect(() => {
-    route.params.sublist?.map((item, index) => {
-      item.list?.map((subitem, index) => {
-        data.push(subitem);
-      });
-    });
-  }, []);
-
-  useEffect(() => {
-    const dataStatistics = getStatistic(selectedValue.url1, selectedValue.url2);
-    const tempData = JSON.parse(dataStatistics as unknown as string) as unknown as StatisticType;
-    setStatisticsData(tempData);
-  }, [selectedValue]);
-
-  if (!selectedValue.url1) return <Loading />;
-  if (!statisticsData) return <Loading />;
-
-  const Item = (data: { name: string; flag: string; cnt: number | string; index: number }) => (
-    <View
-      style={{
-        display: 'flex',
-        alignItems: 'center',
-        flexDirection: 'row',
-        flex: 1,
-        gap: 8
-      }}
-    >
-      <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
-        {data.index + 1}
-      </Text>
-      <Image
-        style={{ width: 36, height: 36, borderRadius: 18 }}
-        source={{ uri: API_HOST + '/img/flags_new/' + data.flag }}
-      />
-      <View
-        style={{
-          flex: 1,
-          display: 'flex',
-          flexDirection: 'row',
-          justifyContent: 'space-between',
-          alignItems: 'center'
-        }}
-      >
-        <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
-          {data.name}
-        </Text>
-        <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{data.cnt}</Text>
-      </View>
-    </View>
-  );
-
-  console.log(statisticsData);
-
-  return (
-    <PageWrapper>
-      <ScrollView showsVerticalScrollIndicator={false}>
-        <Header label={route.params.title} />
-        <Dropdown
-          style={{
-            width: '100%',
-            height: 40,
-            backgroundColor: '#F9F9F9',
-            borderRadius: 4,
-            paddingHorizontal: 8
-          }}
-          placeholderStyle={ModalStyles.placeholderStyle}
-          selectedTextStyle={ModalStyles.selectedTextStyle}
-          data={data}
-          placeholder={'Select'}
-          onChange={(obj) => setSelectedValue(obj)}
-          value={selectedValue?.url1}
-          labelField="name"
-          valueField="url1"
-        />
-        <FlatList
-          data={statisticsData.ranking}
-          renderItem={({ item, index }) => (
-            <View style={{ marginTop: 5, marginBottom: 5 }}>
-              <Item
-                name={`${item.first_name} ${item.last_name}`}
-                flag={item.flag}
-                cnt={item.cnt}
-                index={index}
-              />
-            </View>
-          )}
-        />
-      </ScrollView>
-    </PageWrapper>
-  );
-};
-
-export default NomadsStatistics;

+ 19 - 0
src/screens/InAppScreens/TravellersScreen/StatisticsListScreen/temp.ts → src/screens/InAppScreens/TravellersScreen/StatisticsListScreen/funcs.ts

@@ -1,5 +1,6 @@
 import {
   Type1,
+  Type10,
   Type2,
   Type3,
   Type4,
@@ -138,3 +139,21 @@ export function isType9(obj: any): obj is Type9 {
     'visited_countries' in obj
   );
 }
+
+export function isType10(obj: any): obj is Type10 {
+  const length = Object.keys(obj).length;
+
+  if (length !== 7) {
+    return false;
+  }
+
+  return (
+    'cnt' in obj &&
+    'flags' in obj &&
+    'item_id' in obj &&
+    'item_name' in obj &&
+    'series_icon' in obj &&
+    'series_id' in obj &&
+    'series_name' in obj
+  );
+}

+ 18 - 167
src/screens/InAppScreens/TravellersScreen/StatisticsListScreen/index.tsx

@@ -1,26 +1,21 @@
-import React, { useCallback, useState } from 'react';
-import { FlatList, View, Text } from 'react-native';
-import { Image } from 'expo-image';
+import React, { FC, useCallback, useState } from 'react';
+import { FlatList, Text } from 'react-native';
 import { useFocusEffect } from '@react-navigation/native';
 
+import { RenderItem } from '../Components/StatisticRouter';
+
 import { Header, Loading, PageWrapper } from '../../../../components';
-import { getStatistic, StatisticType, ListType } from '../../../../database/statisticsService';
-import { API_HOST } from '../../../../constants';
-import { Colors } from '../../../../theme';
-import { getFontSize } from '../../../../utils';
-import {
-  isType1,
-  isType2,
-  isType3,
-  isType4,
-  isType5,
-  isType6,
-  isType7,
-  isType8,
-  isType9
-} from './temp';
+import { getStatistic, StatisticType } from '../../../../database/statisticsService';
+
+import { ItemStyles } from '../Components/styles';
+
+type Props = {
+  route: { params: { title: string; url1: string; url2: string | null } };
+};
+
+//TODO: For future fix types
 
-const StatisticsListScreen = ({ route }) => {
+const StatisticsListScreen: FC<Props> = ({ route }) => {
   const title = route.params.title;
   const url1 = route.params.url1;
   const url2 = route.params.url2;
@@ -46,161 +41,17 @@ const StatisticsListScreen = ({ route }) => {
   if (isLoading) return <Loading />;
   if (!statistic) return null;
 
-  const Item = (data: { name: string; flag: string; cnt: number | string; index: number }) => (
-    <View
-      style={{
-        display: 'flex',
-        alignItems: 'center',
-        flexDirection: 'row',
-        flex: 1,
-        gap: 8
-      }}
-    >
-      <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
-        {data.index + 1}
-      </Text>
-      <Image
-        style={{ width: 36, height: 36, borderRadius: 18 }}
-        source={{ uri: API_HOST + '/img/flags_new/' + data.flag }}
-      />
-      <View
-        style={{
-          flex: 1,
-          display: 'flex',
-          flexDirection: 'row',
-          justifyContent: 'space-between',
-          alignItems: 'center'
-        }}
-      >
-        <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
-          {data.name}
-        </Text>
-        <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{data.cnt}</Text>
-      </View>
-    </View>
-  );
-
-  const renderItem = ({ item, index }: { index: number; item: ListType }) => {
-    if (isType1(item) || isType4(item) || isType5(item)) {
-      return (
-        <>
-          {'megaregion' in item && (
-            <View>
-              {item.megaregion !== statistic.ranking[index - 1]?.megaregion ? (
-                <Text
-                  style={{
-                    color: Colors.DARK_BLUE,
-                    fontSize: getFontSize(14),
-                    fontWeight: '700',
-                    textAlign: 'center',
-                    marginTop: 10,
-                    marginBottom: 15
-                  }}
-                >
-                  {item.megaregion as string}
-                </Text>
-              ) : null}
-            </View>
-          )}
-          <Item cnt={item.cnt} flag={item.flag} index={index} name={item.region_name} />
-        </>
-      );
-    } else if (isType6(item)) {
-      return (
-        <>
-          <View>
-            {item.country !== statistic.ranking[index - 1]?.country ? (
-              <Text
-                style={{
-                  color: Colors.DARK_BLUE,
-                  fontSize: getFontSize(14),
-                  fontWeight: '700',
-                  textAlign: 'center',
-                  marginTop: 10,
-                  marginBottom: 15
-                }}
-              >
-                {item.country}
-              </Text>
-            ) : null}
-          </View>
-          <Item cnt={item.cnt} flag={item.region_flag} index={index} name={item.region} />
-        </>
-      );
-    } else if (isType2(item)) {
-      return (
-        <>
-          <View>
-            {item.mega_name !== statistic.ranking[index - 1]?.mega_name ? (
-              <Text
-                style={{
-                  color: Colors.DARK_BLUE,
-                  fontSize: getFontSize(14),
-                  fontWeight: '700',
-                  textAlign: 'center',
-                  marginTop: 10,
-                  marginBottom: 15
-                }}
-              >
-                {item.mega_name as string}
-              </Text>
-            ) : null}
-          </View>
-          <Item name={item.dare_name} flag={item.dare_flag} cnt={item.cnt} index={index} />
-        </>
-      );
-    } else if (isType7(item)) {
-      return <Item name={item.country_name} flag={item.flag} cnt={item.cnt} index={index} />;
-    } else if (isType8(item)) {
-      return (
-        <>
-          <View>
-            {item.mega_name !== statistic.ranking[index - 1]?.mega_name ? (
-              <Text
-                style={{
-                  color: Colors.DARK_BLUE,
-                  fontSize: getFontSize(14),
-                  fontWeight: '700',
-                  textAlign: 'center',
-                  marginTop: 10,
-                  marginBottom: 15
-                }}
-              >
-                {item.mega_name as string}
-              </Text>
-            ) : null}
-            <Item name={item.country} flag={item.flag} cnt={item.cnt} index={index} />
-          </View>
-        </>
-      );
-    } else if (isType9(item)) {
-      return <Item name={item.nation} flag={item.flag} cnt={item.score} index={index} />;
-    } else
-      return (
-        <>
-          <Item
-            name={item.nation ? item.nation : `${item.first_name} ${item.last_name}`}
-            flag={item.flag}
-            cnt={item.score ? item.score : item.cnt}
-            index={index}
-          />
-        </>
-      );
-  };
-
   return (
     <PageWrapper>
       <Header label={title} />
-      {statistic.comment && (
-        <Text style={{ color: Colors.DARK_BLUE, textAlign: 'center', marginBottom: 15 }}>
-          {statistic.comment}
-        </Text>
-      )}
+      {statistic.comment && <Text style={ItemStyles.comment}>{statistic.comment}</Text>}
       <FlatList
         contentContainerStyle={{ gap: 10 }}
         horizontal={false}
         data={statistic.ranking}
-        renderItem={renderItem}
+        renderItem={({ item, index }) => (
+          <RenderItem item={item} index={index} ranking={statistic?.ranking} />
+        )}
         showsVerticalScrollIndicator={false}
       />
     </PageWrapper>

+ 1 - 2
src/types/navigation.ts

@@ -24,6 +24,5 @@ export enum NAVIGATION_PAGES {
   TRAVELS_TAB = 'inAppTravels',
   SERIES = 'inAppSeries',
   SERIES_ITEM = 'inAppSeriesItem',
-  STATISTICS_LIST_DATA = 'statisticsListData',
-  NOMADS_STATISTICS = 'nomadsStatistics'
+  STATISTICS_LIST_DATA = 'statisticsListData'
 }