| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- import React, { useCallback, useEffect, useRef, useState } from 'react';
- import { View, Text, TouchableOpacity, FlatList } from 'react-native';
- import { useFocusEffect, useNavigation } from '@react-navigation/native';
- import { PageWrapper, Header, Modal, FlatList as List, WarningModal } from 'src/components';
- import TripItem from '../Components/TripItem';
- import { useGetTripsYearsQuery, useGetTripsForYearQuery } from '@api/trips';
- import { StoreType, storage } from 'src/storage';
- import { TripsData } from '../utils/types';
- import { NAVIGATION_PAGES } from 'src/types';
- import { styles } from './styles';
- import ChevronIcon from '../../../../../assets/icons/travels-screens/chevron-bottom.svg';
- import AddIcon from '../../../../../assets/icons/travels-screens/circle-plus.svg';
- import TripSvg from '../../../../../assets/icons/travels-screens/trip.svg';
- import InfoIcon from 'assets/icons/info-solid.svg';
- import { Colors } from 'src/theme';
- import ChevronLeftIcon from 'assets/icons/chevron-left.svg';
- import { getFontSize } from 'src/utils';
- import { FlashList, FlashListRef } from '@shopify/flash-list';
- import WarningIcon from 'assets/icons/warning.svg';
- import moment from 'moment';
- const TripsScreen = ({ route }: { route: any }) => {
- const token = storage.get('token', StoreType.STRING) as string;
- const navigation = useNavigation();
- const [isDatePickerVisible, setDatePickerVisible] = useState(false);
- const { data: years, refetch } = useGetTripsYearsQuery(token, true);
- const [selectedYear, setSelectedYear] = useState<string | null>(moment().year().toString());
- const { data: tripsData, refetch: refetchTrips } = useGetTripsForYearQuery(
- token,
- selectedYear as string,
- selectedYear ? true : false
- );
- const [trips, setTrips] = useState<TripsData[]>([]);
- const [statistics, setStatistics] = useState<{
- countries: {
- description: string;
- list: {
- id: number;
- country: string;
- days_spent: number;
- flag: string | null;
- regions: {
- id: number;
- region: string;
- days_spent: number;
- }[];
- }[];
- };
- general: [string];
- regions: {
- description: string;
- list: {
- id: number;
- days_spent: number;
- flag: string | null;
- flag1: string | null;
- flag2: string | null;
- region: string;
- }[];
- };
- dates_missing: 0 | 1;
- } | null>(null);
- const [isWarningModalVisible, setIsWarningModalVisible] = useState(false);
- const flashListRef = useRef<FlashListRef<any> | null>(null);
- useFocusEffect(
- useCallback(() => {
- const fetchData = async () => {
- try {
- await refetch();
- await refetchTrips();
- } catch (error) {
- console.error(error);
- }
- };
- if (route.params?.saved || route.params?.updated || route.params?.deleted) {
- fetchData();
- setIsWarningModalVisible(true);
- }
- }, [route.params])
- );
- useEffect(() => {
- if (years && years.data && !selectedYear) {
- setSelectedYear(years.data[0]);
- }
- }, [years]);
- useEffect(() => {
- if (!isWarningModalVisible) {
- navigation.setParams({ saved: false, updated: false, deleted: false } as never);
- }
- }, [isWarningModalVisible]);
- useEffect(() => {
- if (tripsData && tripsData.trips) {
- setStatistics(tripsData.statistics);
- setTrips(tripsData.trips);
- }
- }, [tripsData]);
- const renderItem = useCallback(
- ({ item }: { item: TripsData }) => (
- <TripItem item={item} isNew={Number(selectedYear) >= 2025} />
- ),
- [selectedYear]
- );
- const onAddNewTripPress = useCallback(() => {
- if (Number(selectedYear) >= 2025) {
- navigation.navigate(NAVIGATION_PAGES.ADD_TRIP_2025 as never);
- } else {
- navigation.navigate(NAVIGATION_PAGES.ADD_TRIP as never);
- }
- }, [navigation, selectedYear]);
- const handleScrollToTrip = () => {
- if (!flashListRef?.current) return;
- const index = trips.findIndex((trip) => trip.dates_missing === 1);
- if (index === -1) return;
- flashListRef.current.scrollToIndex({
- index,
- animated: true,
- viewPosition: 0
- });
- };
- return (
- <PageWrapper>
- <View
- style={{
- alignItems: 'center',
- paddingVertical: 16,
- flexDirection: 'row',
- justifyContent: 'center'
- }}
- >
- <Text
- style={{ color: Colors.DARK_BLUE, fontFamily: 'redhat-700', fontSize: getFontSize(14) }}
- >
- Trips
- </Text>
- </View>
- <View style={styles.tabContainer}>
- <TouchableOpacity style={styles.regionSelector} onPress={() => setDatePickerVisible(true)}>
- <Text style={[styles.regionText]}>{selectedYear}</Text>
- <ChevronIcon />
- </TouchableOpacity>
- <TouchableOpacity style={styles.addNewTab} onPress={onAddNewTripPress}>
- <AddIcon />
- <Text style={styles.addNewTabText}>Add New Trip</Text>
- </TouchableOpacity>
- </View>
- {trips.length === 0 ? (
- <View style={styles.noTripsContainer}>
- <View style={styles.noTripsIcon}>
- <TripSvg fill={Colors.WHITE} />
- </View>
- <Text style={styles.noTripsText}>No trips at the moment</Text>
- </View>
- ) : (
- <FlashList
- ref={flashListRef}
- data={trips}
- renderItem={renderItem}
- keyExtractor={(item, index) => `${item.id}-${index}`}
- style={styles.tripsList}
- contentContainerStyle={styles.tripsListContentContainer}
- showsVerticalScrollIndicator={false}
- ListHeaderComponent={
- Number(selectedYear) >= 2025 ? (
- <View
- style={{
- marginTop: 12,
- marginBottom: 8,
- backgroundColor: Colors.FILL_LIGHT,
- borderRadius: 8,
- paddingHorizontal: 16,
- paddingVertical: 12,
- gap: 6
- }}
- >
- {statistics?.general ? (
- <Text style={{ fontSize: 14, fontWeight: '600', color: Colors.DARK_BLUE }}>
- {statistics.general}
- </Text>
- ) : null}
- <TouchableOpacity
- onPress={() =>
- navigation.navigate(
- ...([
- NAVIGATION_PAGES.REGIONS_VISITED,
- {
- title: statistics?.countries?.description,
- isRegion: false,
- data: statistics?.countries?.list
- }
- ] as never)
- )
- }
- hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
- >
- <Text style={{ fontSize: 14, fontWeight: '600', color: Colors.ORANGE }}>
- {statistics?.countries?.description}
- </Text>
- </TouchableOpacity>
- <TouchableOpacity
- onPress={() =>
- navigation.navigate(
- ...([
- NAVIGATION_PAGES.REGIONS_VISITED,
- {
- title: statistics?.regions?.description,
- isRegion: true,
- data: statistics?.regions?.list
- }
- ] as never)
- )
- }
- hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
- >
- <Text style={{ fontSize: 14, fontWeight: '600', color: Colors.ORANGE }}>
- {statistics?.regions?.description}
- </Text>
- </TouchableOpacity>
- {statistics?.dates_missing ? (
- <TouchableOpacity
- onPress={handleScrollToTrip}
- hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
- style={{ marginTop: 8, flexDirection: 'row', gap: 8, alignItems: 'center' }}
- >
- <WarningIcon color={Colors.RED} width={20} height={20} />
- <Text style={{ fontSize: 14, fontWeight: '600', color: Colors.RED }}>
- For accurate annual statistics, please enter exact dates for all trips.
- </Text>
- </TouchableOpacity>
- ) : null}
- </View>
- ) : null
- }
- />
- )}
- <Modal
- onRequestClose={() => setDatePickerVisible(false)}
- headerTitle={'Select Year'}
- visible={isDatePickerVisible}
- >
- <List
- itemObject={(object) => {
- setSelectedYear(object);
- setDatePickerVisible(false);
- }}
- initialData={years?.data}
- date={true}
- />
- </Modal>
- <WarningModal
- type={'success'}
- isVisible={isWarningModalVisible}
- onClose={() => {
- setIsWarningModalVisible(false);
- }}
- title={
- route.params?.saved
- ? 'Trip added'
- : route.params?.deleted
- ? 'Trip deleted'
- : 'Trip updated'
- }
- message={
- route.params?.saved
- ? 'Trip was successfully added to your list of trips'
- : route.params?.deleted
- ? 'This trip was successfully deleted.'
- : 'Trip was successfully updated'
- }
- />
- </PageWrapper>
- );
- };
- export default TripsScreen;
|