|
@@ -0,0 +1,393 @@
|
|
|
+import React, { useCallback, useEffect, useState } from 'react';
|
|
|
+import { View, Text, TouchableOpacity, ScrollView, FlatList } from 'react-native';
|
|
|
+import ReactModal from 'react-native-modal';
|
|
|
+import * as Progress from 'react-native-progress';
|
|
|
+import { useFocusEffect } from '@react-navigation/native';
|
|
|
+import { Dropdown } from 'react-native-searchable-dropdown-kj';
|
|
|
+import moment from 'moment';
|
|
|
+
|
|
|
+import { Button, Header, PageWrapper, WarningModal } from 'src/components';
|
|
|
+import { CustomButton } from '../Components';
|
|
|
+
|
|
|
+import { StoreType, storage } from 'src/storage';
|
|
|
+import { NmRegion, TCCRegion } from '../utils/types';
|
|
|
+import { Colors } from 'src/theme';
|
|
|
+import { styles } from './styles';
|
|
|
+import {
|
|
|
+ useGetMegaregionsQuery,
|
|
|
+ useGetRegionQeQuery,
|
|
|
+ usePostSetNmRegionMutation,
|
|
|
+ usePostSetTCCRegionMutation
|
|
|
+} from '@api/myRegions';
|
|
|
+import { ButtonVariants } from 'src/types/components';
|
|
|
+import { noOfVisits, qualityOptions } from '../utils/constants';
|
|
|
+
|
|
|
+import ChevronIcon from 'assets/icons/travels-screens/down-arrow.svg';
|
|
|
+import AddImgSvg from 'assets/icons/travels-screens/add-img.svg';
|
|
|
+import { NmRegionItem } from '../Components/MyRegionsItems/NmRegionItem';
|
|
|
+import { TccRegionItem } from '../Components/MyRegionsItems/TccRegionItem';
|
|
|
+
|
|
|
+const RegionsScreen = () => {
|
|
|
+ const token = storage.get('token', StoreType.STRING) as string;
|
|
|
+ const { data: megaregions } = useGetMegaregionsQuery(token, true);
|
|
|
+ const [megaSelectorVisible, setMegaSelectorVisible] = useState(false);
|
|
|
+ const [selectedMega, setSelectedMega] = useState<{ name: string; id: number }>({
|
|
|
+ id: 1,
|
|
|
+ name: 'SOUTHERN EUROPE'
|
|
|
+ });
|
|
|
+ const { data: regionsQe } = useGetRegionQeQuery(selectedMega.id, token, true);
|
|
|
+ const [total, setTotal] = useState(0);
|
|
|
+ const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
|
|
+ const [currentItem, setCurrentItem] = useState<NmRegion | null>(null);
|
|
|
+ const [contentIndex, setContentIndex] = useState(0);
|
|
|
+ const [nmRegions, setNmRegions] = useState<NmRegion[] | null>(null);
|
|
|
+ const [filteredNmRegions, setFilteredNmRegions] = useState<NmRegion[] | null>(null);
|
|
|
+ const [tccRegions, setTccRegions] = useState<TCCRegion[] | null>(null);
|
|
|
+ const [filteredTccRegions, setFilteredTccRegions] = useState<TCCRegion[] | null>(null);
|
|
|
+ const { mutate: updateNM } = usePostSetNmRegionMutation();
|
|
|
+ const { mutate: updateTCC } = usePostSetTCCRegionMutation();
|
|
|
+ const [selectedQuality, setSelectedQuality] = useState(qualityOptions[2]);
|
|
|
+ const [selectedFirstYear, setSelectedFirstYear] = useState(1);
|
|
|
+ const [selectedLastYear, setSelectedLastYear] = useState(1);
|
|
|
+ const [years, setYears] = useState<{ label: string; value: number }[]>([]);
|
|
|
+ const [selectedNoOfVisits, setSelectedNoOfVisits] = useState(1);
|
|
|
+
|
|
|
+ const handleOpenEditModal = (item: NmRegion) => {
|
|
|
+ setCurrentItem(item);
|
|
|
+ setSelectedFirstYear(item.year);
|
|
|
+ setSelectedLastYear(item.last);
|
|
|
+ setSelectedNoOfVisits(item.visits);
|
|
|
+ setSelectedQuality(
|
|
|
+ qualityOptions.find((quality) => quality.id === item.quality) || qualityOptions[2]
|
|
|
+ );
|
|
|
+ setIsEditModalVisible(true);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleUpdateNM = useCallback(
|
|
|
+ (region: number, first: number, last: number, visits: number, quality: number) => {
|
|
|
+ const updatedNM = nmRegions?.map((item) => {
|
|
|
+ if (item.id === region) {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ year: first,
|
|
|
+ last,
|
|
|
+ quality,
|
|
|
+ visits
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+
|
|
|
+ const updatedNMData = {
|
|
|
+ token,
|
|
|
+ region,
|
|
|
+ first,
|
|
|
+ last,
|
|
|
+ visits,
|
|
|
+ quality
|
|
|
+ };
|
|
|
+
|
|
|
+ updateNM(updatedNMData);
|
|
|
+ updatedNM && setNmRegions(updatedNM);
|
|
|
+ },
|
|
|
+ [nmRegions]
|
|
|
+ );
|
|
|
+
|
|
|
+ const handleUpdateTCC = useCallback(
|
|
|
+ (region: number, visits: 0 | 1) => {
|
|
|
+ const updatedTCC = tccRegions?.map((item) => {
|
|
|
+ if (item.id === region) {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ visited: visits
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+
|
|
|
+ const updatedTCCData = {
|
|
|
+ token,
|
|
|
+ region,
|
|
|
+ visits
|
|
|
+ };
|
|
|
+
|
|
|
+ updateTCC(updatedTCCData);
|
|
|
+ updatedTCC && setTccRegions(updatedTCC);
|
|
|
+ },
|
|
|
+ [tccRegions]
|
|
|
+ );
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (nmRegions && nmRegions.length) {
|
|
|
+ calcTotalCountries();
|
|
|
+ }
|
|
|
+ }, [nmRegions]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (regionsQe && regionsQe.result === 'OK') {
|
|
|
+ setNmRegions(regionsQe.data.out_regs);
|
|
|
+ setTccRegions(regionsQe.data.out_tcc);
|
|
|
+ }
|
|
|
+ }, [regionsQe]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (megaregions && megaregions.result === 'OK') {
|
|
|
+ setContentIndex(0);
|
|
|
+ }
|
|
|
+ }, [selectedMega]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ switch (contentIndex) {
|
|
|
+ case 0:
|
|
|
+ setFilteredNmRegions(nmRegions);
|
|
|
+ setFilteredTccRegions(tccRegions);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ setFilteredNmRegions(nmRegions?.filter((item) => item.visits <= 0) || []);
|
|
|
+ setFilteredTccRegions(tccRegions?.filter((item) => item.visited <= 0) || []);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ setFilteredNmRegions(nmRegions?.filter((item) => item.visits > 0) || []);
|
|
|
+ setFilteredTccRegions(tccRegions?.filter((item) => item.visited > 0) || []);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }, [contentIndex, nmRegions, tccRegions]);
|
|
|
+
|
|
|
+ useFocusEffect(
|
|
|
+ useCallback(() => {
|
|
|
+ if (megaregions && megaregions.result === 'OK') {
|
|
|
+ setSelectedMega(megaregions.data[1]);
|
|
|
+
|
|
|
+ const currentYear = moment().year();
|
|
|
+ let yearSelector: { label: string; value: number }[] = [{ label: 'visited', value: 1 }];
|
|
|
+ for (let i = currentYear; i >= 1951; i--) {
|
|
|
+ yearSelector.push({ label: i.toString(), value: i });
|
|
|
+ }
|
|
|
+ setYears(yearSelector);
|
|
|
+ }
|
|
|
+ }, [megaregions])
|
|
|
+ );
|
|
|
+
|
|
|
+ const calcTotalCountries = () => {
|
|
|
+ const visited = nmRegions?.filter((item) => item.visits > 0).length || 0;
|
|
|
+ setTotal(visited);
|
|
|
+ };
|
|
|
+
|
|
|
+ const renderItem = ({ item }: { item: NmRegion }) => (
|
|
|
+ <NmRegionItem item={item} openEditModal={handleOpenEditModal} updateNM={handleUpdateNM} />
|
|
|
+ );
|
|
|
+
|
|
|
+ const renderOption = (name: string) => (
|
|
|
+ <View style={styles.dropdownOption}>
|
|
|
+ <Text style={styles.placeholderStyle}>{name}</Text>
|
|
|
+ </View>
|
|
|
+ );
|
|
|
+
|
|
|
+ return (
|
|
|
+ <PageWrapper>
|
|
|
+ <Header label="Regions" />
|
|
|
+ <TouchableOpacity style={styles.megaSelector} onPress={() => setMegaSelectorVisible(true)}>
|
|
|
+ <Text style={styles.megaButtonText}>{selectedMega?.name}</Text>
|
|
|
+ <ChevronIcon width={18} height={18} />
|
|
|
+ </TouchableOpacity>
|
|
|
+
|
|
|
+ <View style={styles.buttonContainer}>
|
|
|
+ <CustomButton
|
|
|
+ title="All"
|
|
|
+ onPress={() => setContentIndex(0)}
|
|
|
+ isActive={contentIndex === 0}
|
|
|
+ />
|
|
|
+ <CustomButton
|
|
|
+ title="Not visited"
|
|
|
+ onPress={() => setContentIndex(1)}
|
|
|
+ isActive={contentIndex === 1}
|
|
|
+ />
|
|
|
+ <CustomButton
|
|
|
+ title="Visited"
|
|
|
+ onPress={() => setContentIndex(2)}
|
|
|
+ isActive={contentIndex === 2}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+
|
|
|
+ <View style={styles.progressHeader}>
|
|
|
+ <Text style={styles.textSmall}>Visited regions</Text>
|
|
|
+ <Text style={styles.textSmall}>
|
|
|
+ {nmRegions?.length
|
|
|
+ ? `${total}/${nmRegions.length} • ${((total * 100) / nmRegions.length).toFixed(2)}%`
|
|
|
+ : '0/0 • 100%'}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ <Progress.Bar
|
|
|
+ progress={nmRegions?.length ? total / nmRegions.length : 1}
|
|
|
+ width={null}
|
|
|
+ height={4}
|
|
|
+ color={Colors.DARK_BLUE}
|
|
|
+ borderWidth={0}
|
|
|
+ borderRadius={5}
|
|
|
+ unfilledColor={Colors.DARK_LIGHT}
|
|
|
+ />
|
|
|
+
|
|
|
+ {filteredNmRegions && (filteredNmRegions?.length || filteredTccRegions?.length) ? (
|
|
|
+ <FlatList
|
|
|
+ data={filteredNmRegions}
|
|
|
+ renderItem={renderItem}
|
|
|
+ keyExtractor={(item) => item.id.toString()}
|
|
|
+ showsVerticalScrollIndicator={false}
|
|
|
+ style={{ paddingTop: 8, marginBottom: 16 }}
|
|
|
+ ListFooterComponent={
|
|
|
+ filteredTccRegions && filteredTccRegions.length ? (
|
|
|
+ <View style={{ marginTop: 8 }}>
|
|
|
+ <Text style={[styles.textMedium, { textAlign: 'center' }]}>TCC regions</Text>
|
|
|
+ {filteredTccRegions?.map((item) => (
|
|
|
+ <TccRegionItem item={item} updateTCC={handleUpdateTCC} key={item.id} />
|
|
|
+ ))}
|
|
|
+ </View>
|
|
|
+ ) : null
|
|
|
+ }
|
|
|
+ />
|
|
|
+ ) : null}
|
|
|
+
|
|
|
+ <ReactModal
|
|
|
+ isVisible={megaSelectorVisible}
|
|
|
+ onBackdropPress={() => setMegaSelectorVisible(false)}
|
|
|
+ style={styles.modal}
|
|
|
+ statusBarTranslucent={true}
|
|
|
+ presentationStyle="overFullScreen"
|
|
|
+ >
|
|
|
+ <View style={styles.wrapper}>
|
|
|
+ <ScrollView style={{ paddingBottom: 16 }} showsVerticalScrollIndicator={false}>
|
|
|
+ {megaregions?.data?.map((mega) => (
|
|
|
+ <TouchableOpacity
|
|
|
+ key={mega.id}
|
|
|
+ style={styles.btnOption}
|
|
|
+ onPress={() => {
|
|
|
+ setMegaSelectorVisible(false);
|
|
|
+ setSelectedMega(mega);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text style={styles.btnOptionText}>{mega.name}</Text>
|
|
|
+ </TouchableOpacity>
|
|
|
+ ))}
|
|
|
+ </ScrollView>
|
|
|
+ </View>
|
|
|
+ </ReactModal>
|
|
|
+
|
|
|
+ <ReactModal
|
|
|
+ isVisible={isEditModalVisible}
|
|
|
+ onBackdropPress={() => setIsEditModalVisible(false)}
|
|
|
+ style={styles.modal}
|
|
|
+ statusBarTranslucent={true}
|
|
|
+ presentationStyle="overFullScreen"
|
|
|
+ >
|
|
|
+ <View style={styles.modalContent}>
|
|
|
+ <View style={styles.optionsContainer}>
|
|
|
+ <View style={styles.rowWrapper}>
|
|
|
+ <View style={styles.dropdownWrapper}>
|
|
|
+ <Text style={styles.textSmall}>First visit</Text>
|
|
|
+ <Dropdown
|
|
|
+ style={styles.dropdown}
|
|
|
+ placeholderStyle={styles.placeholderStyle}
|
|
|
+ selectedTextStyle={styles.placeholderStyle}
|
|
|
+ data={years}
|
|
|
+ labelField="label"
|
|
|
+ valueField="value"
|
|
|
+ value={selectedFirstYear}
|
|
|
+ placeholder="First visit"
|
|
|
+ onChange={(item) => {
|
|
|
+ setSelectedFirstYear(item.value);
|
|
|
+ setSelectedLastYear(item.value);
|
|
|
+ }}
|
|
|
+ containerStyle={{ borderRadius: 4 }}
|
|
|
+ renderItem={(item) => renderOption(item.label)}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ <View style={styles.dropdownWrapper}>
|
|
|
+ <Text style={styles.textSmall}>Last visit</Text>
|
|
|
+ <Dropdown
|
|
|
+ style={styles.dropdown}
|
|
|
+ placeholderStyle={styles.placeholderStyle}
|
|
|
+ selectedTextStyle={styles.placeholderStyle}
|
|
|
+ data={years.filter((item) => item.value >= selectedFirstYear || item.value === 1)}
|
|
|
+ labelField="label"
|
|
|
+ valueField="value"
|
|
|
+ value={selectedLastYear}
|
|
|
+ placeholder="Last visit"
|
|
|
+ onChange={(item) => setSelectedLastYear(item.value)}
|
|
|
+ containerStyle={{ borderRadius: 4 }}
|
|
|
+ renderItem={(item) => renderOption(item.label)}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <View style={styles.rowWrapper}>
|
|
|
+ <View style={styles.dropdownWrapper}>
|
|
|
+ <Text style={styles.textSmall}>Best visit quality</Text>
|
|
|
+ <Dropdown
|
|
|
+ style={styles.dropdown}
|
|
|
+ placeholderStyle={styles.placeholderStyle}
|
|
|
+ containerStyle={{ borderRadius: 4 }}
|
|
|
+ selectedTextStyle={styles.placeholderStyle}
|
|
|
+ data={qualityOptions}
|
|
|
+ labelField="name"
|
|
|
+ valueField="id"
|
|
|
+ value={selectedQuality.id}
|
|
|
+ placeholder="Best visit quality"
|
|
|
+ onChange={(item) => setSelectedQuality(item)}
|
|
|
+ renderItem={(item) => renderOption(item.name)}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ <View style={styles.dropdownWrapper}>
|
|
|
+ <Text style={styles.textSmall}>No of visits</Text>
|
|
|
+ <Dropdown
|
|
|
+ style={styles.dropdown}
|
|
|
+ placeholderStyle={styles.placeholderStyle}
|
|
|
+ selectedTextStyle={styles.placeholderStyle}
|
|
|
+ data={noOfVisits}
|
|
|
+ labelField="label"
|
|
|
+ valueField="value"
|
|
|
+ value={selectedNoOfVisits}
|
|
|
+ placeholder="No of visits"
|
|
|
+ onChange={(item) => setSelectedNoOfVisits(item.value)}
|
|
|
+ containerStyle={{ borderRadius: 4 }}
|
|
|
+ renderItem={(item) => renderOption(item.label)}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <View style={styles.photosContent}>
|
|
|
+ <Text style={styles.textMedium}>Photos</Text>
|
|
|
+ <TouchableOpacity style={styles.addImgBtn}>
|
|
|
+ <AddImgSvg fill={Colors.DARK_BLUE} />
|
|
|
+ <Text style={styles.textSmall}>Add</Text>
|
|
|
+ </TouchableOpacity>
|
|
|
+ </View>
|
|
|
+ <Button
|
|
|
+ children="Done"
|
|
|
+ onPress={() => {
|
|
|
+ setIsEditModalVisible(false);
|
|
|
+ currentItem?.id &&
|
|
|
+ handleUpdateNM(
|
|
|
+ currentItem.id,
|
|
|
+ selectedFirstYear,
|
|
|
+ selectedLastYear,
|
|
|
+ selectedNoOfVisits,
|
|
|
+ selectedQuality.id
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ children="Close"
|
|
|
+ onPress={() => setIsEditModalVisible(false)}
|
|
|
+ variant={ButtonVariants.OPACITY}
|
|
|
+ containerStyles={styles.closeBtn}
|
|
|
+ textStyles={{ color: Colors.DARK_BLUE }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </ReactModal>
|
|
|
+ </PageWrapper>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default RegionsScreen;
|