Explorar o código

feat: UNMasters screen

Oleksandr Honcharov hai 1 ano
pai
achega
fe72346528

+ 3 - 0
assets/icons/arrow-up-wide-short.svg

@@ -0,0 +1,3 @@
+<svg width="20" height="18" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.05645 1.36619C4.84167 1.1338 4.54237 1 4.22547 1C3.90858 1 3.60928 1.1338 3.39449 1.36619L0.295927 4.74645C-0.123084 5.20419 -0.0949151 5.91898 0.366349 6.33799C0.827613 6.757 1.53888 6.72883 1.95789 6.26757L3.09872 5.02462V15.6478C3.09872 16.271 3.60224 16.7745 4.22547 16.7745C4.84871 16.7745 5.35223 16.271 5.35223 15.6478V5.02462L6.49306 6.27109C6.91207 6.72883 7.62686 6.76052 8.0846 6.34151C8.54234 5.9225 8.57403 5.20771 8.15502 4.74997L5.05645 1.36972V1.36619ZM10.986 16.7745H12.1127C12.736 16.7745 13.2395 16.271 13.2395 15.6478C13.2395 15.0245 12.736 14.521 12.1127 14.521H10.986C10.3628 14.521 9.85923 15.0245 9.85923 15.6478C9.85923 16.271 10.3628 16.7745 10.986 16.7745ZM10.986 12.2675H14.3662C14.9895 12.2675 15.493 11.764 15.493 11.1408C15.493 10.5175 14.9895 10.014 14.3662 10.014H10.986C10.3628 10.014 9.85923 10.5175 9.85923 11.1408C9.85923 11.764 10.3628 12.2675 10.986 12.2675ZM10.986 7.76051H16.6197C17.243 7.76051 17.7465 7.25699 17.7465 6.63376C17.7465 6.01053 17.243 5.50701 16.6197 5.50701H10.986C10.3628 5.50701 9.85923 6.01053 9.85923 6.63376C9.85923 7.25699 10.3628 7.76051 10.986 7.76051ZM10.986 3.2535H18.8732C19.4965 3.2535 20 2.74999 20 2.12675C20 1.50352 19.4965 1 18.8732 1H10.986C10.3628 1 9.85923 1.50352 9.85923 2.12675C9.85923 2.74999 10.3628 3.2535 10.986 3.2535Z" fill="#0F3F4F"/>
+</svg>

+ 107 - 29
src/screens/InAppScreens/TravellersScreen/UNMasters/index.tsx

@@ -1,47 +1,125 @@
-import React, { useCallback, useState } from 'react';
-import { FlatList, View, Text } from 'react-native';
-import { useFocusEffect } from '@react-navigation/native';
+import React, { useEffect, useState } from 'react';
+import { FlatList, Text, TouchableOpacity, View } from 'react-native';
+import { Image } from 'expo-image';
 
-import HorizontalSelect from '../Components/HorizontalSelect';
+import { Header, HorizontalTabView, Loading, PageWrapper } from '../../../../components';
+import { getMastersByType, getUNMastersTypes } from '../../../../database/unMastersService';
+import { API_HOST } from '../../../../constants';
 
-import { Header, Loading, PageWrapper } from '../../../../components';
-import { getMastersByType } from '../../../../database/unMastersService';
-import type { Master, TypeData } from '../../../../database/unMastersService';
+import { UNMastersListStyles } from './styles';
+
+import ArrowUpWideIcon from '../../../../../assets/icons/arrow-up-wide-short.svg';
+
+import type { Master } from '../../../../database/unMastersService';
 
 const UNMastersScreen = () => {
-  const [selectedType, setSelectedType] = useState<TypeData | null>(null);
-  const [masters, setMasters] = useState<Master[] | null>([]);
-  const [isLoading, setIsLoading] = useState(true);
+  const [index, setIndex] = useState(0);
+  const [routes, setRoutes] = useState<{ key: string; title: string }[]>([]);
+  const [loading, setLoading] = useState(true);
 
-  useFocusEffect(
-    useCallback(() => {
-      const fetchType = async () => {
-        const data = getMastersByType(selectedType?.type || 1);
-        setMasters(data);
-        setIsLoading(false);
-      };
+  useEffect(() => {
+    const types = getUNMastersTypes();
 
-      fetchType();
-    }, [])
-  );
+    const parseRoutes = types?.map((item) => ({
+      key: item.type.toString(),
+      title: item.name
+    }));
 
-  if (isLoading) return <Loading />;
+    setRoutes(parseRoutes || []);
+    setLoading(false);
+  }, []);
+
+  if (loading) return <Loading />;
 
   return (
     <PageWrapper>
       <Header label={'UN Masters'} />
-      <HorizontalSelect selectedType={(type) => setSelectedType(type)} />
-      <FlatList
-        maxToRenderPerBatch={20}
-        data={masters}
-        renderItem={({ item }) => (
-          <View style={{ borderStyle: 'solid', borderWidth: 1, borderColor: 'red' }}>
-            <Text>{item.age}</Text>
-          </View>
+      <HorizontalTabView
+        index={index}
+        setIndex={setIndex}
+        routes={routes}
+        renderScene={({ route }: { route: { key: string; title: string } }) => (
+          <UNMastersList type={route.key} />
         )}
       />
     </PageWrapper>
   );
 };
 
+const UNMastersList = React.memo(({ type }: { type: string }) => {
+  const [isLoading, setIsLoading] = useState(true);
+  const [masters, setMasters] = useState<Master[] | null>([]);
+
+  useEffect(() => {
+    const fetchType = async () => {
+      const data = getMastersByType(Number(type) || 1);
+      setMasters(data);
+    };
+
+    fetchType();
+    setIsLoading(false);
+  }, [type]);
+
+  if (isLoading) return <Loading />;
+
+  const renderItem = ({ item }: { item: Master }) => {
+    return (
+      <View style={UNMastersListStyles.wrapper}>
+        <View>
+          <Image
+            style={UNMastersListStyles.avatar}
+            source={{ uri: API_HOST + '/img/avatars/' + `-1.webp` }}
+          />
+        </View>
+        <View style={{ gap: 3, marginLeft: 5 }}>
+          <Text style={UNMastersListStyles.firstAndLastName}>{item.full_name}</Text>
+          <View style={UNMastersListStyles.wrapper}>
+            <Text style={UNMastersListStyles.descriptionText}>
+              Born: {item.born} / Age when done: {item.age} /
+            </Text>
+            <Image
+              style={[UNMastersListStyles.countryFlag, { marginLeft: 5 }]}
+              source={{ uri: API_HOST + '/img/flags_new/' + item.origin1_flag }}
+            />
+            {item.origin2_flag && item.origin2_flag !== item.origin1_flag ? (
+              <Image
+                style={[UNMastersListStyles.countryFlag, { marginLeft: -5 }]}
+                source={{ uri: API_HOST + '/img/flags_new/' + item.origin2_flag }}
+              />
+            ) : null}
+          </View>
+          <View style={UNMastersListStyles.wrapper}>
+            <Text style={UNMastersListStyles.descriptionText}>
+              Year / final country: {item.final_year}
+            </Text>
+            <Image
+              style={[UNMastersListStyles.countryFlag, { marginLeft: 5 }]}
+              source={{ uri: API_HOST + '/img/flags_new/' + item.final_flag }}
+            />
+          </View>
+        </View>
+      </View>
+    );
+  };
+
+  return (
+    <>
+      <TouchableOpacity style={UNMastersListStyles.sortButton}>
+        <ArrowUpWideIcon />
+        <Text style={[UNMastersListStyles.descriptionText, { marginLeft: 5 }]}>
+          Sorted by country of origin / year of completion
+        </Text>
+      </TouchableOpacity>
+      <FlatList
+        contentContainerStyle={{ gap: 10 }}
+        horizontal={false}
+        data={masters}
+        renderItem={renderItem}
+        keyExtractor={(item) => item.id.toString()}
+        showsVerticalScrollIndicator={false}
+      />
+    </>
+  );
+});
+
 export default UNMastersScreen;

+ 43 - 0
src/screens/InAppScreens/TravellersScreen/UNMasters/styles.ts

@@ -0,0 +1,43 @@
+import { StyleSheet } from 'react-native';
+import { Colors } from '../../../../theme';
+import { getFontSize } from '../../../../utils';
+
+export const UNMastersListStyles = StyleSheet.create({
+  wrapper: {
+    display: 'flex',
+    flexDirection: 'row',
+    alignItems: 'center'
+  },
+  firstAndLastName: {
+    fontFamily: 'redhat-700',
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(14)
+  },
+  avatar: {
+    borderRadius: 24,
+    width: 48,
+    height: 48,
+    marginTop: 3,
+    marginBottom: 3,
+    alignSelf: 'center'
+  },
+  descriptionText: {
+    color: Colors.DARK_BLUE,
+    fontSize: getFontSize(12),
+    fontWeight: '600'
+  },
+  countryFlag: {
+    width: 20,
+    height: 20,
+    borderRadius: 20 / 2,
+    borderWidth: 0.5,
+    borderColor: 'gray'
+  },
+  sortButton: {
+    paddingTop: 20,
+    paddingBottom: 20,
+    display: 'flex',
+    flexDirection: 'row',
+    alignItems: 'center'
+  }
+});