瀏覽代碼

feat: statistics redesign

Oleksandr Honcharov 1 年之前
父節點
當前提交
28ebc1ef8f

+ 5 - 0
Route.tsx

@@ -27,6 +27,7 @@ import InMemoriamScreen from './src/screens/InAppScreens/TravellersScreen/InMemo
 import InHistoryScreen from './src/screens/InAppScreens/TravellersScreen/InHistoryScreen';
 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 SeriesScreen from 'src/screens/InAppScreens/TravelsScreen/Series';
 
@@ -147,6 +148,10 @@ const Route = () => {
                     name={NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW}
                     component={ProfileScreen}
                   />
+                  <ScreenStack.Screen
+                    name={NAVIGATION_PAGES.STATISTICS_LIST_DATA}
+                    component={StatisticsListScreen}
+                  />
                 </ScreenStack.Navigator>
               )}
             </BottomTab.Screen>

+ 1 - 1
assets/icons/mark-to-up.svg

@@ -1,3 +1,3 @@
 <svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M1 1.7074L4.29293 5.00033C4.68182 5.38921 5.31818 5.38921 5.70707 5.00033L9 1.7074" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M1 1.7074L4.29293 5.00033C4.68182 5.38921 5.31818 5.38921 5.70707 5.00033L9 1.7074" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
 </svg>

+ 1 - 1
src/database/statisticsService/index.ts

@@ -85,7 +85,7 @@ export function getList(): List[] | null {
   return loadData<List[]>('list');
 }
 
-interface ListData {
+export interface ListData {
   name: string;
   url1: string;
   url2?: string | null;

+ 132 - 0
src/screens/InAppScreens/TravellersScreen/StatisticsListScreen/index.tsx

@@ -0,0 +1,132 @@
+import React, { useEffect, useState } from 'react';
+import { FlatList, View, Text } from 'react-native';
+import { Image } from 'expo-image';
+
+import { Header, Loading, PageWrapper } from '../../../../components';
+import {
+  getStatistic,
+  StatisticType,
+  Type2,
+  Type1,
+  Type3
+} from '../../../../database/statisticsService';
+import { API_HOST } from '../../../../constants';
+import { Colors } from '../../../../theme';
+import { getFontSize } from '../../../../utils';
+
+const StatisticsListScreen = ({ route }) => {
+  const title = route.params.title;
+  const url1 = route.params.url1;
+
+  const [isLoading, setIsLoading] = useState(true);
+  const [statistic, setStatistic] = useState<StatisticType | null>(null);
+
+  useEffect(() => {
+    const data = getStatistic(url1);
+
+    if (!data) return;
+
+    setStatistic(JSON.parse(data as unknown as string) as unknown as StatisticType);
+    setIsLoading(false);
+  }, []);
+
+  if (isLoading) return <Loading />;
+  if (!statistic) return null;
+
+  console.log(statistic);
+
+  const renderItem = ({ item, index }: { index: number; item: Type1 | Type2 | Type3 }) => {
+    if ('region_id' in item) {
+      return (
+        <View
+          style={{
+            display: 'flex',
+            alignItems: 'center',
+            flexDirection: 'row',
+            flex: 1,
+            gap: 8
+          }}
+        >
+          <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
+            {index + 1}
+          </Text>
+          <Image
+            style={{ width: 36, height: 36, borderRadius: 18 }}
+            source={{ uri: API_HOST + '/img/flags_new/' + (item.flag ?? item.region_flag) }}
+          />
+          <View
+            style={{
+              flex: 1,
+              display: 'flex',
+              flexDirection: 'row',
+              justifyContent: 'space-between',
+              alignItems: 'center'
+            }}
+          >
+            <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
+              {item.region_name ?? item.region}
+            </Text>
+            <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{item.cnt}</Text>
+          </View>
+        </View>
+      );
+    } else if ('mega_id' in item) {
+      return (
+        <View
+          style={{
+            display: 'flex',
+            alignItems: 'center',
+            flexDirection: 'row',
+            flex: 1,
+            gap: 8
+          }}
+        >
+          <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
+            {index + 1}
+          </Text>
+          <Image
+            style={{ width: 36, height: 36, borderRadius: 18 }}
+            source={{ uri: API_HOST + '/img/flags_new/' + item.dare_flag }}
+          />
+          <View
+            style={{
+              flex: 1,
+              display: 'flex',
+              flexDirection: 'row',
+              justifyContent: 'space-between',
+              alignItems: 'center'
+            }}
+          >
+            <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
+              {item.dare_name}
+            </Text>
+            <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{item.cnt}</Text>
+          </View>
+        </View>
+      );
+    } else if ('user' in item) {
+      return (
+        <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
+          <Text>
+            {item.first_name} {item.last_name}
+          </Text>
+        </View>
+      );
+    }
+  };
+
+  return (
+    <PageWrapper>
+      <Header label={title} />
+      <FlatList
+        contentContainerStyle={{ gap: 10 }}
+        horizontal={false}
+        data={statistic.ranking}
+        renderItem={renderItem}
+        showsVerticalScrollIndicator={false}
+      />
+    </PageWrapper>
+  );
+};
+
+export default StatisticsListScreen;

+ 197 - 152
src/screens/InAppScreens/TravellersScreen/StatisticsScreen/index.tsx

@@ -1,25 +1,20 @@
 import React, { useEffect, useState } from 'react';
-import {
-  getList,
-  getStatistic,
-  StatisticType,
-  Type2,
-  Type1,
-  Type3
-} from '../../../../database/statisticsService';
-import { Header, HorizontalTabView, Loading, PageWrapper } from '../../../../components';
+import { getList, ListData } from '../../../../database/statisticsService';
+import { Header, Loading, PageWrapper } from '../../../../components';
 
-import { FlatList, Text, View } from 'react-native';
+import { Text, TouchableOpacity, View } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+import { NAVIGATION_PAGES } from '../../../../types';
 import { Colors } from '../../../../theme';
-import { getFontSize } from '../../../../utils';
-import { Image } from 'expo-image';
-import { API_HOST } from '../../../../constants';
+import ArrowIcon from '../../../../../assets/icons/mark-to-up.svg';
 
 const StatisticsScreen = () => {
-  const [index, setIndex] = useState(0);
-  const [routes, setRoutes] = useState<{ key: string; title: string }[]>([]);
+  const [index, setIndex] = useState(null);
+  const [routes, setRoutes] = useState<{ key: string; title: string; list?: ListData[] }[]>([]);
   const [loading, setLoading] = useState(true);
 
+  const navigation = useNavigation();
+
   useEffect(() => {
     const types = getList();
 
@@ -40,148 +35,198 @@ const StatisticsScreen = () => {
     <>
       <PageWrapper>
         <Header label={'Statistics'} />
-        <HorizontalTabView
-          index={index}
-          setIndex={setIndex}
-          withMark={true}
-          routes={routes}
-          renderScene={({ route }: Data) => <StatisticsList list={route.list} />}
-          onDoubleClick={() => console.log('double click')}
-        />
+        <View style={{ gap: 20 }}>
+          {routes.map((route, i) => {
+            return (
+              <View>
+                <TouchableOpacity
+                  onPress={() => setIndex(index === i ? null : i)}
+                  style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}
+                >
+                  <Text
+                    style={[{ fontSize: 20, color: 'rgba(237, 147, 52, 1)', fontWeight: '700' }]}
+                  >
+                    {route.title}
+                  </Text>
+                  <View style={index === i ? { transform: 'rotate(180deg)' } : {}}>
+                    <ArrowIcon height={18} width={18} stroke={'#B7C6CB'} />
+                  </View>
+                </TouchableOpacity>
+                {index === i && (
+                  <View>
+                    {route.list?.map((item, index) => {
+                      return (
+                        <TouchableOpacity
+                          onPress={() =>
+                            navigation.navigate(NAVIGATION_PAGES.STATISTICS_LIST_DATA, {
+                              title: item.name,
+                              type: route.title,
+                              url1: item.url1
+                            })
+                          }
+                        >
+                          <Text
+                            style={{
+                              marginTop: 12,
+                              marginBottom: 5,
+                              marginLeft: 10,
+                              color: Colors.DARK_BLUE,
+                              fontWeight: '700'
+                            }}
+                          >
+                            {item.name}
+                          </Text>
+                        </TouchableOpacity>
+                      );
+                    })}
+                  </View>
+                )}
+              </View>
+            );
+          })}
+        </View>
+        {/*<HorizontalTabView*/}
+        {/*  index={index}*/}
+        {/*  setIndex={setIndex}*/}
+        {/*  withMark={true}*/}
+        {/*  routes={routes}*/}
+        {/*  renderScene={({ route }: Data) => <></>}*/}
+        {/*  onDoubleClick={() => console.log('double click')}*/}
+        {/*/>*/}
       </PageWrapper>
     </>
   );
 };
 
-const StatisticsList = React.memo(({ list }: { list: { name: string; url1: string }[] }) => {
-  const [isLoading, setIsLoading] = useState(true);
-  const [statistic, setStatistic] = useState<StatisticType | null>(null);
-
-  useEffect(() => {
-    const data = getStatistic(list ? list[0]?.url1 : '');
-
-    if (!data) return;
-
-    setStatistic(JSON.parse(data as unknown as string) as unknown as StatisticType);
-    setIsLoading(false);
-  }, []);
-
-  if (isLoading) return <Loading />;
-  if (!statistic) return null;
-
-  const renderItem = ({ item, index }: { index: number; item: Type1 | Type2 | Type3 }) => {
-    if ('region_id' in item) {
-      return (
-        <View
-          style={{
-            display: 'flex',
-            alignItems: 'center',
-            flexDirection: 'row',
-            flex: 1,
-            gap: 8
-          }}
-        >
-          <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
-            {index + 1}
-          </Text>
-          <Image
-            style={{ width: 36, height: 36, borderRadius: 18 }}
-            source={{ uri: API_HOST + '/img/flags_new/' + item.flag }}
-          />
-          <View
-            style={{
-              flex: 1,
-              display: 'flex',
-              flexDirection: 'row',
-              justifyContent: 'space-between',
-              alignItems: 'center'
-            }}
-          >
-            <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
-              {item.region_name}
-            </Text>
-            <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{item.cnt}</Text>
-          </View>
-        </View>
-      );
-    } else if ('mega_id' in item) {
-      return (
-        <View
-          style={{
-            display: 'flex',
-            alignItems: 'center',
-            flexDirection: 'row',
-            flex: 1,
-            gap: 8
-          }}
-        >
-          <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
-            {index + 1}
-          </Text>
-          <Image
-            style={{ width: 36, height: 36, borderRadius: 18 }}
-            source={{ uri: API_HOST + '/img/flags_new/' + item.dare_flag }}
-          />
-          <View
-            style={{
-              flex: 1,
-              display: 'flex',
-              flexDirection: 'row',
-              justifyContent: 'space-between',
-              alignItems: 'center'
-            }}
-          >
-            <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
-              {item.dare_name}
-            </Text>
-            <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{item.cnt}</Text>
-          </View>
-        </View>
-      );
-    } else if ('user' in item) {
-      return (
-        <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
-          <Text>
-            {item.first_name} {item.last_name}
-          </Text>
-        </View>
-      );
-    }
-  };
-
-  return (
-    <>
-      <View
-        style={{
-          width: '100%',
-          display: 'flex',
-          justifyContent: 'center',
-          alignItems: 'center',
-          marginTop: 10,
-          marginBottom: 10
-        }}
-      >
-        <Text
-          style={{
-            color: Colors.DARK_BLUE,
-            fontSize: getFontSize(16),
-            fontWeight: '700',
-            textAlign: 'center'
-          }}
-        >
-          {statistic?.name}
-        </Text>
-      </View>
-      <FlatList
-        contentContainerStyle={{ gap: 10 }}
-        horizontal={false}
-        data={statistic.ranking}
-        renderItem={renderItem}
-        showsVerticalScrollIndicator={false}
-      />
-    </>
-  );
-});
+// const StatisticsList = React.memo(({ list }: { list: { name: string; url1: string }[] }) => {
+//   const [isLoading, setIsLoading] = useState(true);
+//   const [statistic, setStatistic] = useState<StatisticType | null>(null);
+//
+//   useEffect(() => {
+//     const data = getStatistic(list ? list[0]?.url1 : '');
+//
+//     if (!data) return;
+//
+//     setStatistic(JSON.parse(data as unknown as string) as unknown as StatisticType);
+//     setIsLoading(false);
+//   }, []);
+//
+//   if (isLoading) return <Loading />;
+//   if (!statistic) return null;
+//
+//   const renderItem = ({ item, index }: { index: number; item: Type1 | Type2 | Type3 }) => {
+//     if ('region_id' in item) {
+//       return (
+//         <View
+//           style={{
+//             display: 'flex',
+//             alignItems: 'center',
+//             flexDirection: 'row',
+//             flex: 1,
+//             gap: 8
+//           }}
+//         >
+//           <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
+//             {index + 1}
+//           </Text>
+//           <Image
+//             style={{ width: 36, height: 36, borderRadius: 18 }}
+//             source={{ uri: API_HOST + '/img/flags_new/' + item.flag }}
+//           />
+//           <View
+//             style={{
+//               flex: 1,
+//               display: 'flex',
+//               flexDirection: 'row',
+//               justifyContent: 'space-between',
+//               alignItems: 'center'
+//             }}
+//           >
+//             <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
+//               {item.region_name}
+//             </Text>
+//             <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{item.cnt}</Text>
+//           </View>
+//         </View>
+//       );
+//     } else if ('mega_id' in item) {
+//       return (
+//         <View
+//           style={{
+//             display: 'flex',
+//             alignItems: 'center',
+//             flexDirection: 'row',
+//             flex: 1,
+//             gap: 8
+//           }}
+//         >
+//           <Text style={{ color: Colors.DARK_BLUE, fontSize: getFontSize(18), fontWeight: '700' }}>
+//             {index + 1}
+//           </Text>
+//           <Image
+//             style={{ width: 36, height: 36, borderRadius: 18 }}
+//             source={{ uri: API_HOST + '/img/flags_new/' + item.dare_flag }}
+//           />
+//           <View
+//             style={{
+//               flex: 1,
+//               display: 'flex',
+//               flexDirection: 'row',
+//               justifyContent: 'space-between',
+//               alignItems: 'center'
+//             }}
+//           >
+//             <Text style={{ width: '75%', color: Colors.DARK_BLUE, fontWeight: '700' }}>
+//               {item.dare_name}
+//             </Text>
+//             <Text style={{ color: Colors.DARK_BLUE, fontWeight: '700' }}>{item.cnt}</Text>
+//           </View>
+//         </View>
+//       );
+//     } else if ('user' in item) {
+//       return (
+//         <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
+//           <Text>
+//             {item.first_name} {item.last_name}
+//           </Text>
+//         </View>
+//       );
+//     }
+//   };
+//
+//   return (
+//     <>
+//       <View
+//         style={{
+//           width: '100%',
+//           display: 'flex',
+//           justifyContent: 'center',
+//           alignItems: 'center',
+//           marginTop: 10,
+//           marginBottom: 10
+//         }}
+//       >
+//         <Text
+//           style={{
+//             color: Colors.DARK_BLUE,
+//             fontSize: getFontSize(16),
+//             fontWeight: '700',
+//             textAlign: 'center'
+//           }}
+//         >
+//           {statistic?.name}
+//         </Text>
+//       </View>
+//       <FlatList
+//         contentContainerStyle={{ gap: 10 }}
+//         horizontal={false}
+//         data={statistic.ranking}
+//         renderItem={renderItem}
+//         showsVerticalScrollIndicator={false}
+//       />
+//     </>
+//   );
+// });
 
 type Data = {
   route: {

+ 1 - 0
src/types/navigation.ts

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