Viktoriia преди 1 година
родител
ревизия
ced2882105
променени са 23 файла, в които са добавени 386 реда и са изтрити 40 реда
  1. 5 2
      Route.tsx
  2. 3 0
      assets/icons/calendar-check.svg
  3. 40 4
      src/components/Calendars/RangeCalendar/index.tsx
  4. 3 0
      src/modules/api/triumphs/index.ts
  5. 2 0
      src/modules/api/triumphs/queries/index.ts
  6. 17 0
      src/modules/api/triumphs/queries/use-post-get-data.tsx
  7. 17 0
      src/modules/api/triumphs/queries/use-post-get-dates.tsx
  8. 25 0
      src/modules/api/triumphs/triumphs-api.tsx
  9. 4 0
      src/modules/api/triumphs/triumphs-query-keys.tsx
  10. 13 12
      src/screens/InAppScreens/MapScreen/index.tsx
  11. 49 0
      src/screens/InAppScreens/TravellersScreen/Components/TriumphItem.tsx
  12. 49 1
      src/screens/InAppScreens/TravellersScreen/Components/styles.ts
  13. 86 0
      src/screens/InAppScreens/TravellersScreen/TriumphsScreen/index.tsx
  14. 27 0
      src/screens/InAppScreens/TravellersScreen/TriumphsScreen/styles.tsx
  15. 4 1
      src/screens/InAppScreens/TravellersScreen/index.tsx
  16. 11 0
      src/screens/InAppScreens/TravellersScreen/utils/types.ts
  17. 1 1
      src/screens/InAppScreens/TravelsScreen/AddNewTripScreen/index.tsx
  18. 1 1
      src/screens/InAppScreens/TravelsScreen/AddPhotoScreen/index.tsx
  19. 3 2
      src/screens/InAppScreens/TravelsScreen/Components/PhotoEditModal.tsx
  20. 13 11
      src/screens/InAppScreens/TravelsScreen/MorePhotosScreen/index.tsx
  21. 4 2
      src/screens/InAppScreens/TravelsScreen/Series/index.tsx
  22. 8 3
      src/types/api.ts
  23. 1 0
      src/types/navigation.ts

+ 5 - 2
Route.tsx

@@ -28,6 +28,7 @@ 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 TriumphsScreen from 'src/screens/InAppScreens/TravellersScreen/TriumphsScreen';
 
 import SeriesScreen from 'src/screens/InAppScreens/TravelsScreen/Series';
 import { SeriesItemScreen } from 'src/screens/InAppScreens/TravelsScreen/SeriesItemScreen';
@@ -55,8 +56,6 @@ const BottomTab = createBottomTabNavigator();
 
 SplashScreen.preventAutoHideAsync();
 
-//TODO: Fix types on Statistics
-
 const Route = () => {
   const token = storage.get('token', StoreType.STRING);
 
@@ -165,6 +164,10 @@ const Route = () => {
                     name={NAVIGATION_PAGES.STATISTICS_LIST_DATA}
                     component={StatisticsListScreen}
                   />
+                  <ScreenStack.Screen
+                    name={NAVIGATION_PAGES.TRIUMPHS}
+                    component={TriumphsScreen}
+                  />
                 </ScreenStack.Navigator>
               )}
             </BottomTab.Screen>

+ 3 - 0
assets/icons/calendar-check.svg

@@ -0,0 +1,3 @@
+<svg width="15" height="17" viewBox="0 0 15 17" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.5 0.5C4.91563 0.5 5.25 0.834375 5.25 1.25V2.5H9.75V1.25C9.75 0.834375 10.0844 0.5 10.5 0.5C10.9156 0.5 11.25 0.834375 11.25 1.25V2.5H12.5C13.6031 2.5 14.5 3.39687 14.5 4.5V5V6.5V14.5C14.5 15.6031 13.6031 16.5 12.5 16.5H2.5C1.39688 16.5 0.5 15.6031 0.5 14.5V6.5V5V4.5C0.5 3.39687 1.39688 2.5 2.5 2.5H3.75V1.25C3.75 0.834375 4.08437 0.5 4.5 0.5ZM13 6.5H2V14.5C2 14.775 2.225 15 2.5 15H12.5C12.775 15 13 14.775 13 14.5V6.5ZM10.7812 9.78125L7.28125 13.2812C6.9875 13.575 6.5125 13.575 6.22188 13.2812L4.22187 11.2812C3.92812 10.9875 3.92812 10.5125 4.22187 10.2219C4.51562 9.93125 4.99062 9.92813 5.28125 10.2219L6.75 11.6906L9.71875 8.72188C10.0125 8.42813 10.4875 8.42813 10.7781 8.72188C11.0687 9.01562 11.0719 9.49063 10.7781 9.78125H10.7812Z" fill="#0F3F4F"/>
+</svg>

+ 40 - 4
src/components/Calendars/RangeCalendar/index.tsx

@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
 import { View } from 'react-native';
 import moment from 'moment';
 import { Modal } from '../../Modal';
@@ -14,14 +14,24 @@ export default function RangeCalendar({
   closeModal,
   allowRangeSelection = true,
   disableFutureDates = false,
+  highlightedDates,
+  selectedDate
 }: {
   isModalVisible: boolean;
-  closeModal: (startDate?: Date | null, endDate?: Date | null) => void;
+  closeModal: (startDate?: string | null, endDate?: string | null) => void;
   allowRangeSelection?: boolean;
   disableFutureDates?: boolean;
+  highlightedDates?: string[];
+  selectedDate?: string;
 }) {
-  const [selectedStartDate, setSelectedStartDate] = useState<Date | null>(null);
-  const [selectedEndDate, setSelectedEndDate] = useState<Date | null>(null);
+  const [selectedStartDate, setSelectedStartDate] = useState<string | null>(null);
+  const [selectedEndDate, setSelectedEndDate] = useState<string | null>(null);
+
+  useEffect(() => {
+    if (selectedDate) {
+      setSelectedStartDate(selectedDate);
+    }
+  }, [selectedDate]);
 
   const customThemeStyles = {
     textSectionTitleColor: Colors.ORANGE,
@@ -66,6 +76,15 @@ export default function RangeCalendar({
     const marked: { [key: string]: any } = {};
     let start = selectedStartDate as unknown as string;
     let end = selectedEndDate as unknown as string;
+    if (selectedDate && !selectedStartDate) {
+      marked[selectedDate] = {
+        selected: true,
+        startingDay: true,
+        endingDay: true,
+        color: Colors.ORANGE,
+        textColor: 'white',
+      };
+    }
     if (disableFutureDates) {
       const today = moment().add(1, 'day');
       const lastDay = moment().add(2, 'years');
@@ -77,6 +96,20 @@ export default function RangeCalendar({
         today.add(1, 'day');
       }
     }
+    if (highlightedDates) {
+      const datesSet = new Set(highlightedDates);
+
+      const startDateMoment = moment(highlightedDates[0]);
+      const endDateMoment = moment(highlightedDates[highlightedDates.length - 1]);
+    
+      for (let m = moment(startDateMoment); m.diff(endDateMoment, 'days') <= 0; m.add(1, 'days')) {
+        const dateString = m.format('YYYY-MM-DD');
+        if (!datesSet.has(dateString)) {
+          marked[dateString] = { disableTouchEvent: true, disabled: true };
+        }
+      }
+
+    }
     if (start && end) {
       marked[start] = { startingDay: true, color: Colors.ORANGE, textColor: 'white' };
       let day = start;
@@ -129,6 +162,9 @@ export default function RangeCalendar({
           theme={{
             ...customThemeStyles,
           }}
+          minDate={highlightedDates ? highlightedDates[0] : undefined}
+          maxDate={highlightedDates ? highlightedDates[highlightedDates.length - 1] : undefined}
+          current={selectedDate}
         />
       </View>
       <View style={styles.modalFooter}>

+ 3 - 0
src/modules/api/triumphs/index.ts

@@ -0,0 +1,3 @@
+export * from './queries';
+export * from './triumphs-api';
+export * from './triumphs-query-keys';

+ 2 - 0
src/modules/api/triumphs/queries/index.ts

@@ -0,0 +1,2 @@
+export * from './use-post-get-dates';
+export * from './use-post-get-data';

+ 17 - 0
src/modules/api/triumphs/queries/use-post-get-data.tsx

@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { triumphsQueryKeys } from '../triumphs-query-keys';
+import { triumphsApi, type PostGetDates } from '../triumphs-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const useGetTriumphsDates = (enabled: boolean) => {
+  return useQuery<PostGetDates, BaseAxiosError>({
+    queryKey: triumphsQueryKeys.getDates(),
+    queryFn: async () => {
+      const response = await triumphsApi.getDates();
+      return response.data;
+    },
+    enabled
+  });
+};

+ 17 - 0
src/modules/api/triumphs/queries/use-post-get-dates.tsx

@@ -0,0 +1,17 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { triumphsQueryKeys } from '../triumphs-query-keys';
+import { triumphsApi, type PostGetData } from '../triumphs-api';
+
+import type { BaseAxiosError } from '../../../../types';
+
+export const useGetTriumphsData = (date: string, enabled: boolean) => {
+  return useQuery<PostGetData, BaseAxiosError>({
+    queryKey: triumphsQueryKeys.getData(date),
+    queryFn: async () => {
+      const response = await triumphsApi.getData(date);
+      return response.data;
+    },
+    enabled
+  });
+};

+ 25 - 0
src/modules/api/triumphs/triumphs-api.tsx

@@ -0,0 +1,25 @@
+import { request } from '../../../utils';
+import { API } from '../../../types';
+import { ResponseType } from '../response-type';
+
+export interface PostGetDates extends ResponseType {
+  dates: string[];
+}
+
+export interface PostGetData extends ResponseType {
+  triumphs: {
+    user_id: number;
+    name: string;
+    type: string;
+    treshold: number;
+    avatar: string | null;
+    flag: string;
+    text: string;
+    icon: string;
+  }[];
+}
+
+export const triumphsApi = {
+  getDates: () => request.postForm<PostGetDates>(API.GET_TRIUMPHS_DATES),
+  getData: (date: string) => request.postForm<PostGetData>(API.GET_TRIUMPHS_DATA, { date })
+};

+ 4 - 0
src/modules/api/triumphs/triumphs-query-keys.tsx

@@ -0,0 +1,4 @@
+export const triumphsQueryKeys = {
+  getDates: () => ['getDates'] as const,
+  getData: (date: string) => ['getData', date] as const
+};

+ 13 - 12
src/screens/InAppScreens/MapScreen/index.tsx

@@ -188,22 +188,23 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
       (region: { properties: { id: any } }) => region.properties.id
     );
 
-    isConnected && await mutateAsync(
-      { regions: JSON.stringify(regionIds), token: String(token) },
-      {
-        onSuccess: (data) => {
-          if (thisToken !== currentTokenRef.current) return;
+    isConnected &&
+      (await mutateAsync(
+        { regions: JSON.stringify(regionIds), token: String(token) },
+        {
+          onSuccess: (data) => {
+            if (thisToken !== currentTokenRef.current) return;
 
-          setSeries(data.series);
+            setSeries(data.series);
 
-          const markersVisible = filterCandidatesMarkers(data.items, visibleAreaPolygon);
-          const allMarkers = markersVisible.map(processMarkerData);
-          const clusteredMarkers = clusterMarkers(allMarkers, currentZoom, setClusters);
+            const markersVisible = filterCandidatesMarkers(data.items, visibleAreaPolygon);
+            const allMarkers = markersVisible.map(processMarkerData);
+            const clusteredMarkers = clusterMarkers(allMarkers, currentZoom, setClusters);
 
-          setMarkers(clusteredMarkers as MarkerData[]);
+            setMarkers(clusteredMarkers as MarkerData[]);
+          }
         }
-      }
-    );
+      ));
   };
 
   const renderMarkers = () => {

+ 49 - 0
src/screens/InAppScreens/TravellersScreen/Components/TriumphItem.tsx

@@ -0,0 +1,49 @@
+import React, { useCallback } from 'react';
+import { View, Image, TouchableOpacity, Text } from 'react-native';
+
+import { AvatarWithInitials } from 'src/components';
+import { API_HOST } from 'src/constants';
+import { TriumphsStyles } from './styles';
+import { TriumphsData } from '../utils/types';
+
+export const TriumphItem = React.memo(
+  ({ item, onPress }: { item: TriumphsData; onPress: (userId: number) => void }) => {
+    const [firstPart, secondPart] = item.text.split(' reached ');
+    const [firstName, lastName] = item.name.split(' ');
+
+    const handlePress = useCallback(() => {
+      onPress(item.user_id);
+    }, [item.user_id, onPress]);
+
+    return (
+      <TouchableOpacity onPress={handlePress} style={TriumphsStyles.itemContainer}>
+        {item.avatar ? (
+          <View>
+            <Image source={{ uri: API_HOST + item.avatar }} style={TriumphsStyles.avatar} />
+            <Image source={{ uri: API_HOST + item.flag }} style={TriumphsStyles.flag} />
+          </View>
+        ) : (
+          <AvatarWithInitials
+            text={`${firstName[0] ?? ''}${lastName[0] ?? ''}`}
+            flag={API_HOST + item.flag}
+            size={48}
+          />
+        )}
+        <View style={{ flex: 1 }}>
+          <Text style={TriumphsStyles.text}>{item.name}</Text>
+          <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
+            <Text style={TriumphsStyles.text}>
+              <Text style={TriumphsStyles.reached}>reached </Text>
+              <Text>{secondPart}</Text>
+            </Text>
+          </View>
+        </View>
+
+        <View style={TriumphsStyles.tresholdContainer}>
+          <Image source={{ uri: API_HOST + item.icon }} style={TriumphsStyles.icon} />
+          <Text style={TriumphsStyles.treshold}>{item.treshold}</Text>
+        </View>
+      </TouchableOpacity>
+    );
+  }
+);

+ 49 - 1
src/screens/InAppScreens/TravellersScreen/Components/styles.ts

@@ -273,6 +273,54 @@ export const ItemStyles = StyleSheet.create({
   comment: {
     color: Colors.DARK_BLUE,
     textAlign: 'center',
-    marginBottom: 8,
+    marginBottom: 8
+  }
+});
+
+export const TriumphsStyles = StyleSheet.create({
+  itemContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    gap: 8
+  },
+  avatar: {
+    width: 48,
+    height: 48,
+    borderRadius: 24,
+    borderWidth: 1,
+    borderColor: Colors.DARK_LIGHT
+  },
+  flag: {
+    width: 20,
+    height: 20,
+    borderRadius: 10,
+    borderWidth: 1,
+    borderColor: Colors.DARK_LIGHT,
+    position: 'absolute',
+    top: 0,
+    right: 0
+  },
+  text: {
+    fontSize: 14,
+    fontWeight: '600',
+    color: Colors.ORANGE
+  },
+  reached: {
+    color: Colors.DARK_BLUE,
+    fontWeight: '400'
+  },
+  icon: {
+    width: 24,
+    height: 24
+  },
+  tresholdContainer: {
+    alignItems: 'center',
+    justifyContent: 'center',
+    gap: 3
+  },
+  treshold: {
+    fontSize: 14,
+    fontWeight: '600',
+    color: Colors.DARK_BLUE
   }
 });

+ 86 - 0
src/screens/InAppScreens/TravellersScreen/TriumphsScreen/index.tsx

@@ -0,0 +1,86 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { FlatList, Text, TouchableOpacity } from 'react-native';
+import moment from 'moment';
+
+import { Header, PageWrapper, WarningModal } from 'src/components';
+import RangeCalendar from 'src/components/Calendars/RangeCalendar';
+
+import { useGetTriumphsDates, useGetTriumphsData } from '@api/triumphs';
+import { TriumphsData } from '../utils/types';
+import { styles } from './styles';
+
+import CalendarSvg from 'assets/icons/calendar-check.svg';
+import { useConnection } from 'src/contexts/ConnectionContext';
+import { StoreType, storage } from 'src/storage';
+import { useNavigation } from '@react-navigation/native';
+import { NAVIGATION_PAGES } from 'src/types';
+import { TriumphItem } from '../Components/TriumphItem';
+
+const TriumphsScreen = () => {
+  const navigation = useNavigation();
+  const netInfo = useConnection();
+  const token = storage.get('token', StoreType.STRING);
+  const [selectedDate, setSelectedDate] = useState<string>(moment().format('YYYY-MM-DD'));
+  const { data: dates } = useGetTriumphsDates(true);
+  const { data } = useGetTriumphsData(selectedDate, true);
+  const [isCalendarVisible, setIsCalendarVisible] = useState(false);
+  const [modalType, setModalType] = useState<string | null>(null);
+
+  useEffect(() => {
+    if (dates) {
+      setSelectedDate(dates.dates[dates.dates.length - 1]);
+    }
+  }, [dates]);
+
+  const handlePress = useCallback(
+    (userId: number) => {
+      if (!netInfo?.isInternetReachable) {
+        setModalType('offline');
+      } else if (!token) {
+        setModalType('unauthorized');
+      } else {
+        navigation.navigate(...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId }] as never));
+      }
+    },
+    [netInfo?.isInternetReachable, token]
+  );
+
+  const renderItem = ({ item }: { item: TriumphsData }) => (
+    <TriumphItem item={item} onPress={handlePress} />
+  );
+
+  return (
+    <PageWrapper>
+      <Header label="Triumphs" />
+      <TouchableOpacity style={styles.dateBtn} onPress={() => setIsCalendarVisible(true)}>
+        <CalendarSvg />
+        <Text style={styles.dateText}>{moment(selectedDate).format('DD, MMMM YYYY')}</Text>
+      </TouchableOpacity>
+      {data && data.triumphs ? (
+        <FlatList
+          data={data.triumphs}
+          renderItem={renderItem}
+          keyExtractor={(item, index) => index.toString()}
+          contentContainerStyle={styles.listContainer}
+          showsVerticalScrollIndicator={false}
+          maxToRenderPerBatch={30}
+        />
+      ) : null}
+      <RangeCalendar
+        isModalVisible={isCalendarVisible}
+        closeModal={(startDate?: string | null, endDate?: string | null) => {
+          startDate && setSelectedDate(startDate);
+          setIsCalendarVisible(false);
+        }}
+        allowRangeSelection={false}
+        highlightedDates={dates?.dates}
+        selectedDate={selectedDate}
+      />
+      {modalType && (
+        <WarningModal type={modalType} isVisible={true} onClose={() => setModalType(null)} />
+      )}
+    </PageWrapper>
+  );
+};
+
+export default TriumphsScreen;

+ 27 - 0
src/screens/InAppScreens/TravellersScreen/TriumphsScreen/styles.tsx

@@ -0,0 +1,27 @@
+import { StyleSheet } from 'react-native';
+import { Colors } from 'src/theme';
+import { getFontSize } from 'src/utils';
+
+export const styles = StyleSheet.create({
+  dateBtn: {
+    flexDirection: 'row',
+    borderWidth: 1,
+    borderColor: Colors.BORDER_LIGHT,
+    borderRadius: 17,
+    alignItems: 'center',
+    paddingHorizontal: 16,
+    paddingVertical: 10,
+    gap: 10,
+    justifyContent: 'center',
+    marginBottom: 8
+  },
+  dateText: {
+    fontWeight: 'bold',
+    fontSize: getFontSize(14),
+    color: Colors.DARK_BLUE
+  },
+  listContainer: {
+    paddingVertical: 16,
+    gap: 16
+  }
+});

+ 4 - 1
src/screens/InAppScreens/TravellersScreen/index.tsx

@@ -65,7 +65,10 @@ const buttons: MenuButtonType[] = [
   },
   {
     label: 'Triumphs',
-    icon: <TrophyIcon fill={Colors.DARK_BLUE} width={20} height={20} />
+    icon: <TrophyIcon fill={Colors.DARK_BLUE} width={20} height={20} />,
+    buttonFn: (navigation) => {
+      navigation.navigate(NAVIGATION_PAGES.TRIUMPHS);
+    }
   }
 ];
 

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

@@ -25,3 +25,14 @@ export type ModalProps = {
 export type FilterButtonProps = {
   onPress: () => void;
 };
+
+export interface TriumphsData {
+  user_id: number;
+  name: string;
+  type: string;
+  treshold: number;
+  avatar: string | null;
+  flag: string;
+  text: string;
+  icon: string;
+}

+ 1 - 1
src/screens/InAppScreens/TravelsScreen/AddNewTripScreen/index.tsx

@@ -312,7 +312,7 @@ const AddNewTripScreen = ({ route }: { route: any }) => {
 
       <RangeCalendar
         isModalVisible={calendarVisible}
-        closeModal={(startDate?: Date | null, endDate?: Date | null) => {
+        closeModal={(startDate?: string | null, endDate?: string | null) => {
           startDate &&
             setSelectedDates(
               startDate.toString() + ' - ' + (endDate ? endDate?.toString() : startDate?.toString())

+ 1 - 1
src/screens/InAppScreens/TravelsScreen/AddPhotoScreen/index.tsx

@@ -297,7 +297,7 @@ const AddPhotoScreen = ({ route }: { route: any }) => {
 
       <RangeCalendar
         isModalVisible={calendarVisible}
-        closeModal={(startDate?: Date | null, endDate?: Date | null) => {
+        closeModal={(startDate?: string | null, endDate?: string | null) => {
           startDate && setSelectedDate(startDate.toString());
           setCalendarVisible(false);
         }}

+ 3 - 2
src/screens/InAppScreens/TravelsScreen/Components/PhotoEditModal.tsx

@@ -114,11 +114,12 @@ export const PhotoEditModal = ({
 
             <RangeCalendar
               isModalVisible={calendarVisible}
-              closeModal={(date: Date | null) => {
-                date && setSelectedDate(date.toISOString().split('T')[0]);
+              closeModal={(startDate?: string | null, endDate?: string | null) => {
+                startDate && setSelectedDate(startDate);
                 setCalendarVisible(false);
               }}
               allowRangeSelection={false}
+              disableFutureDates={true}
             />
           </View>
           <View style={styles.saveBtn}>

+ 13 - 11
src/screens/InAppScreens/TravelsScreen/MorePhotosScreen/index.tsx

@@ -129,24 +129,26 @@ const MorePhotosScreen = ({ route }: { route: any }) => {
           onSuccess: (res) => {
             if (res.result === 'OK') {
               const filteredPhotos = photos.filter((photo) => {
-                if (selectedRegion && selectedRegion?.id !== data?.region) {
+                if (selectedRegion && !data?.date && selectedRegion?.id !== data?.region) {
                   return photo.id !== photoToEdit.id;
-                } else if (selectedDate && selectedDate !== data?.date) {
+                } else if (selectedDate && data?.date && selectedDate !== data?.date) {
                   return photo.id !== photoToEdit.id;
                 } else {
                   return true;
                 }
               });
 
-              const updatedPhotos =
-                typeof description === 'string'
-                  ? filteredPhotos.map((photo) => {
-                      if (photo.id === photoToEdit.id) {
-                        return { ...photo, title: description };
-                      }
-                      return photo;
-                    })
-                  : filteredPhotos;
+              const updatedPhotos = filteredPhotos.map((photo) => {
+                if (photo.id === photoToEdit.id) {
+                  return {
+                    ...photo,
+                    title: typeof description === 'string' ? description : photo.title,
+                    date: selectedDate ?? photo.date,
+                    region: selectedRegion?.id ?? photo.region
+                  };
+                }
+                return photo;
+              });
 
               setPhotos(updatedPhotos);
             }

+ 4 - 2
src/screens/InAppScreens/TravelsScreen/Series/index.tsx

@@ -77,13 +77,15 @@ const SeriesScreen = () => {
         index={index}
         setIndex={setIndex}
         routes={routes}
-        renderScene={({ route }: { route: SeriesGroup }) => <SeriesList groupId={route.key} navigation={navigation} />}
+        renderScene={({ route }: { route: SeriesGroup }) => (
+          <SeriesList groupId={route.key} navigation={navigation} />
+        )}
       />
     </PageWrapper>
   );
 };
 
-const SeriesList = React.memo(({ groupId, navigation }: { groupId: string, navigation: any }) => {
+const SeriesList = React.memo(({ groupId, navigation }: { groupId: string; navigation: any }) => {
   const [seriesData, setSeriesData] = useState<SeriesList[]>([]);
   const [isLoading, setIsLoading] = useState(true);
 

+ 8 - 3
src/types/api.ts

@@ -12,7 +12,8 @@ export enum API_ROUTE {
   PHOTOS = 'photos',
   TRIPS = 'trips',
   SLOW = 'slow',
-  QUICK_ENTER = 'quickEnter'
+  QUICK_ENTER = 'quickEnter',
+  TRIUMPHS = 'triumphs'
 }
 
 export enum API_ENDPOINT {
@@ -68,7 +69,9 @@ export enum API_ENDPOINT {
   SET_TCC_REGION = 'updateTCC',
   GET_MEGAREGIONS_DARE = 'get-megaregions-dare',
   GET_REGIONS_DARE = 'get-regions-dare',
-  SET_DARE_REGION = 'updateDARE'
+  SET_DARE_REGION = 'updateDARE',
+  GET_TRIUMPHS_DATES = 'get-dates-app',
+  GET_TRIUMPHS_DATA = 'get-data-app'
 }
 
 export enum API {
@@ -123,7 +126,9 @@ export enum API {
   SET_TCC_REGION = `${API_ROUTE.QUICK_ENTER}/${API_ENDPOINT.SET_TCC_REGION}`,
   GET_MEGAREGIONS_DARE = `${API_ROUTE.REGIONS}/${API_ENDPOINT.GET_MEGAREGIONS_DARE}`,
   GET_REGIONS_DARE = `${API_ROUTE.REGIONS}/${API_ENDPOINT.GET_REGIONS_DARE}`,
-  SET_DARE_REGION = `${API_ROUTE.QUICK_ENTER}/${API_ENDPOINT.SET_DARE_REGION}`
+  SET_DARE_REGION = `${API_ROUTE.QUICK_ENTER}/${API_ENDPOINT.SET_DARE_REGION}`,
+  GET_TRIUMPHS_DATES = `${API_ROUTE.TRIUMPHS}/${API_ENDPOINT.GET_TRIUMPHS_DATES}`,
+  GET_TRIUMPHS_DATA = `${API_ROUTE.TRIUMPHS}/${API_ENDPOINT.GET_TRIUMPHS_DATA}`
 }
 
 export type BaseAxiosError = AxiosError;

+ 1 - 0
src/types/navigation.ts

@@ -35,4 +35,5 @@ export enum NAVIGATION_PAGES {
   COUNTRIES = 'inAppCountries',
   REGIONS = 'inAppRegions',
   DARE = 'inAppDare',
+  TRIUMPHS = 'inAppTriumphs',
 }