123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- import React, { FC, useCallback, useEffect, useState } from 'react';
- import { Linking, ScrollView, Text, TouchableOpacity, View, Image, Platform } from 'react-native';
- import { CommonActions, NavigationProp, useFocusEffect } from '@react-navigation/native';
- import ReactModal from 'react-native-modal';
- import { usePostGetProfileInfoDataQuery, usePostGetProfileUpdatesQuery } from '@api/user';
- import {
- PageWrapper,
- Loading,
- AvatarWithInitials,
- Header,
- WarningModal
- } from '../../../components';
- import { adaptiveStyle, Colors } from '../../../theme';
- import { styles } from './styles';
- import { API_HOST } from '../../../constants';
- import { NAVIGATION_PAGES } from '../../../types';
- import { storage, StoreType } from '../../../storage';
- import { getFontSize } from '../../../utils';
- import IconFacebook from '../../../../assets/icons/facebook.svg';
- import IconInstagram from '../../../../assets/icons/instagram.svg';
- import IconTwitter from '../../../../assets/icons/x(twitter).svg';
- import IconYouTube from '../../../../assets/icons/youtube.svg';
- import IconGlobe from '../../../../assets/icons/bottom-navigation/globe.svg';
- import IconLink from '../../../../assets/icons/link.svg';
- import GearIcon from '../../../../assets/icons/gear.svg';
- import TBTIcon from '../../../../assets/icons/tbt.svg';
- import TickIcon from '../../../../assets/icons/tick.svg';
- import UNIcon from '../../../../assets/icons/un_icon.svg';
- import NMIcon from '../../../../assets/icons/nm_icon.svg';
- import UN50Icon from '../../../../assets/icons/un-50.svg';
- import UN100Icon from '../../../../assets/icons/un-100.svg';
- import UN150Icon from '../../../../assets/icons/un-150.svg';
- import ChevronIcon from '../../../../assets/icons/chevron-left.svg';
- import ShareIcon from '../../../../assets/icons/share.svg';
- import UnverifiedIcon from '../../../../assets/icons/unverified.svg';
- import { ProfileStyles, ScoreStyles, TBTStyles } from '../TravellersScreen/Components/styles';
- import UnauthenticatedProfileScreen from './UnauthenticatedProfileScreen';
- import { PersonalInfo } from './Components/PersonalInfo';
- import { usePostUpdateFriendStatusMutation } from '@api/friends';
- import Tooltip from 'react-native-walkthrough-tooltip';
- type Props = {
- navigation: NavigationProp<any>;
- route: any;
- };
- const ProfileScreen: FC<Props> = ({ navigation, route }) => {
- const isPublicView = route.name === NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW;
- const token = storage.get('token', StoreType.STRING) as string;
- const currentUserId = storage.get('uid', StoreType.STRING) as string;
- if (!token) return <UnauthenticatedProfileScreen />;
- const { data: userData, isFetching } = usePostGetProfileInfoDataQuery(
- token,
- isPublicView ? route.params?.userId : +currentUserId,
- true
- );
- const { data: lastUpdates } = usePostGetProfileUpdatesQuery(
- token,
- isPublicView ? route.params?.userId : +currentUserId,
- true
- );
- const { mutateAsync: updateFriendStatus } = usePostUpdateFriendStatusMutation();
- const [isFriend, setIsFriend] = React.useState<0 | 1>(0);
- const [shouldOpenWarningModal, setShouldOpenWarningModal] = useState(false);
- const [modalState, setModalState] = useState({
- isModalVisible: false,
- isWarningVisible: false
- });
- const [tooltipVisible, setTooltipVisible] = useState(false);
- useFocusEffect(
- useCallback(() => {
- if (!route.params?.hideTabBar) {
- navigation.getParent()?.setOptions({
- tabBarStyle: {
- display: 'flex',
- ...Platform.select({
- android: {
- height: 58
- }
- })
- }
- });
- }
- }, [navigation])
- );
- useEffect(() => {
- setIsFriend(userData?.data?.is_friend ?? 0);
- if (userData && userData?.data?.own_profile === 1) {
- const userInfo = {
- avatar: userData?.data?.user_data.avatar ?? '',
- first_name: userData?.data?.user_data.first_name,
- last_name: userData?.data?.user_data.last_name,
- homebase_flag: userData?.data?.user_data.flag1
- };
- storage.set('currentUserData', JSON.stringify(userInfo));
- }
- }, [userData]);
- if (!userData?.data || !lastUpdates || isFetching) return <Loading />;
- const data = userData.data;
- const links = JSON.parse(data.user_data.links_json);
- const handleGoToMap = () => {
- data.own_profile === 0
- ? navigation.navigate(NAVIGATION_PAGES.USERS_MAP, { userId: route.params?.userId, data })
- : navigation.dispatch(
- CommonActions.reset({
- index: 1,
- routes: [{ name: NAVIGATION_PAGES.IN_APP_MAP_TAB }]
- })
- );
- };
- const closeModal = (modalName: string) => {
- setModalState((prevState) => ({ ...prevState, [modalName]: false }));
- };
- const openModal = (modalName: string) => {
- setModalState((prevState) => ({ ...prevState, [modalName]: true }));
- };
- const TBRanking = () => {
- const colors = [
- 'rgba(237, 147, 52, 1)',
- 'rgba(128, 128, 128, 1)',
- 'rgba(211, 211, 211, 1)',
- 'rgba(187, 95, 5, 1)',
- '#808080'
- ];
- const Rank = ({ color }: { color: string }) => (
- <View style={adaptiveStyle([ProfileStyles.badge, { backgroundColor: color }], {})}>
- <TBTIcon />
- </View>
- );
- return (
- <TouchableOpacity
- style={adaptiveStyle([TBTStyles.badgeRoot, styles.badgeRoot], {})}
- disabled={!data.scores.rank_tbt || data.scores.rank_tbt < 1}
- >
- <View style={adaptiveStyle([TBTStyles.badgeWrapper, { gap: 10 }], {})}>
- {data.user_data.badge_tbt && data.scores.rank_tbt ? (
- <Rank color={colors[data.scores.rank_tbt - 1]} />
- ) : null}
- {data.scores.rank_tbt && data.scores.rank_tbt >= 1 ? (
- <Text style={adaptiveStyle([ScoreStyles.scoreNameText], {})}>
- TBT # {data.scores.rank_tbt}
- </Text>
- ) : (
- <View style={{ height: 11 }} />
- )}
- </View>
- </TouchableOpacity>
- );
- };
- const handleOpenUrl = (url: string | undefined) => {
- url && Linking.openURL(url);
- };
- const hasActiveLinks = () => {
- return (
- (links?.f?.link && links?.f?.active !== 0) ||
- (links?.i?.link && links?.i?.active !== 0) ||
- (links?.t?.link && links?.t?.active !== 0) ||
- (links?.y?.link && links?.y?.active !== 0) ||
- (links?.www?.link && links?.www?.active !== 0) ||
- (links?.other?.link && links?.other?.active !== 0)
- );
- };
- const handleUpdateFriendStatus = async () => {
- await updateFriendStatus(
- { token: token as string, id: data.friend_db_id, status: -1 },
- {
- onSuccess: () => {
- setIsFriend(0);
- }
- }
- );
- };
- return (
- <PageWrapper>
- <Header label="Profile" />
- <ScrollView
- showsVerticalScrollIndicator={false}
- contentContainerStyle={{ paddingBottom: 58 }}
- >
- <TouchableOpacity
- style={[styles.usersMap, { backgroundColor: '#EBF2F5' }]}
- onPress={handleGoToMap}
- >
- <Image
- source={{
- uri: `${API_HOST}/img/single_maps/${isPublicView ? route.params?.userId : currentUserId}.png`
- }}
- style={styles.usersMap}
- />
- </TouchableOpacity>
- <View style={styles.pageWrapper}>
- <View style={{ gap: 8 }}>
- {data.user_data.avatar ? (
- <Image
- style={styles.avatar}
- source={{ uri: API_HOST + '/img/avatars/' + data.user_data.avatar }}
- />
- ) : (
- <AvatarWithInitials
- text={`${data.user_data.first_name[0] ?? ''}${data.user_data.last_name[0] ?? ''}`}
- flag={API_HOST + '/img/flags_new/' + data.user_data.flag1}
- size={64}
- borderColor={Colors.WHITE}
- />
- )}
- {data.scores.rank_tbt && data.scores.rank_tbt >= 1 ? <TBRanking /> : null}
- {isFriend === 1 && token && data.own_profile === 0 ? (
- <TouchableOpacity style={styles.friend} onPress={() => openModal('isModalVisible')}>
- <Text style={styles.friendText}>Friend</Text>
- <View style={{ transform: 'rotate(180deg)' }}>
- <ChevronIcon fill={Colors.WHITE} height={8} />
- </View>
- </TouchableOpacity>
- ) : null}
- </View>
- <View style={{ gap: 5, flex: 1 }}>
- <View style={{ height: 34 }}></View>
- <View style={styles.nameRow}>
- <Text style={[styles.headerText, { fontSize: getFontSize(18) }]}>
- {data.user_data.first_name} {data.user_data.last_name}
- </Text>
- </View>
- <View style={styles.userInfoContainer}>
- <View style={styles.userInfo}>
- <Text style={styles.ageText}>Age: {data.user_data.age}</Text>
- <Image
- source={{ uri: API_HOST + '/img/flags_new/' + data.user_data.flag1 }}
- style={styles.countryFlag}
- />
- {data.user_data.flag2 && data.user_data.flag2 !== data.user_data.flag1 ? (
- <Image
- source={{ uri: API_HOST + '/img/flags_new/' + data.user_data.flag2 }}
- style={[styles.countryFlag, { marginLeft: -15 }]}
- />
- ) : null}
- <View style={adaptiveStyle(ProfileStyles.badgesWrapper, {})}>
- {data.user_data.auth ? <TickIcon /> : null}
- {data.user_data.badge_un ? <UNIcon /> : null}
- {data.user_data.badge_nm ? <NMIcon /> : null}
- {data.user_data.badge_un_150 ? <UN150Icon /> : null}
- {data.user_data.badge_un_100 ? <UN100Icon /> : null}
- {data.user_data.badge_un_50 ? <UN50Icon /> : null}
- {data.user_data.badge_ghost ? (
- <Tooltip
- isVisible={tooltipVisible}
- onClose={() => setTooltipVisible(false)}
- content={<Text style={{ color: Colors.DARK_BLUE }}>Unverified User</Text>}
- contentStyle={{ backgroundColor: Colors.WHITE }}
- backgroundColor="transparent"
- allowChildInteraction={false}
- placement="top"
- >
- <TouchableOpacity onPress={() => setTooltipVisible(true)}>
- <UnverifiedIcon />
- </TouchableOpacity>
- </Tooltip>
- ) : null}
- </View>
- </View>
- {data.own_profile === 1 ? (
- <>
- <TouchableOpacity
- style={[styles.settings, { right: 25 }]}
- onPress={() =>
- navigation.navigate(NAVIGATION_PAGES.SHARE_PROFILE, {
- data: {
- avatar: data.user_data.avatar,
- first_name: data.user_data.first_name,
- last_name: data.user_data.last_name,
- flag1: data.user_data.flag1,
- flag2: data.user_data.flag2,
- id: +currentUserId,
- auth: data.user_data.auth,
- badge_un: data.user_data.badge_un,
- badge_nm: data.user_data.badge_nm,
- badge_un_50: data.user_data.badge_un_50,
- badge_un_100: data.user_data.badge_un_100,
- badge_un_150: data.user_data.badge_un_150,
- scores: data.scores
- }
- })
- }
- >
- <ShareIcon
- width={20}
- height={20}
- fill={Colors.DARK_BLUE}
- style={{ alignSelf: 'center' }}
- />
- </TouchableOpacity>
- <TouchableOpacity
- style={styles.settings}
- onPress={() => navigation.navigate(NAVIGATION_PAGES.EDIT_PERSONAL_INFO)}
- >
- <GearIcon
- width={20}
- height={20}
- fill={Colors.DARK_BLUE}
- style={{ alignSelf: 'center' }}
- />
- </TouchableOpacity>
- </>
- ) : null}
- </View>
- {hasActiveLinks() && (
- <View style={styles.linksBox}>
- {links?.f?.link && links?.f?.active !== 0 ? (
- <TouchableOpacity onPress={() => handleOpenUrl(links?.f?.link)}>
- <IconFacebook fill={Colors.DARK_BLUE} height={16} />
- </TouchableOpacity>
- ) : null}
- {links?.i?.link && links?.i?.active !== 0 ? (
- <TouchableOpacity onPress={() => handleOpenUrl(links?.i?.link)}>
- <IconInstagram fill={Colors.DARK_BLUE} height={16} />
- </TouchableOpacity>
- ) : null}
- {links?.t?.link && links?.t?.active !== 0 ? (
- <TouchableOpacity onPress={() => handleOpenUrl(links?.t?.link)}>
- <IconTwitter fill={Colors.DARK_BLUE} height={16} />
- </TouchableOpacity>
- ) : null}
- {links?.y?.link && links?.y?.active !== 0 ? (
- <TouchableOpacity onPress={() => handleOpenUrl(links?.y?.link)}>
- <IconYouTube fill={Colors.DARK_BLUE} height={16} />
- </TouchableOpacity>
- ) : null}
- {links?.www?.link && links?.www?.active !== 0 ? (
- <TouchableOpacity onPress={() => handleOpenUrl(links?.www?.link)}>
- <IconGlobe fill={Colors.DARK_BLUE} height={16} />
- </TouchableOpacity>
- ) : null}
- {links?.other?.link && links?.other?.active !== 0 ? (
- <TouchableOpacity onPress={() => handleOpenUrl(links?.other?.link)}>
- <IconLink fill={Colors.DARK_BLUE} height={16} />
- </TouchableOpacity>
- ) : null}
- </View>
- )}
- </View>
- </View>
- <PersonalInfo
- data={{
- bio: data.user_data.bio,
- scores: data.scores,
- homebase: data.user_data.homeregion,
- series: data.series,
- friends: data.friends,
- firstName: data.user_data.first_name,
- lastName: data.user_data.last_name,
- friendRequestSent: data.friend_request_sent,
- friendRequestReceived: data.friend_request_received,
- isFriend,
- friendDbId: data.friend_db_id,
- ownProfile: data.own_profile
- }}
- updates={lastUpdates?.data ? lastUpdates.data?.updates : null}
- userId={isPublicView ? route.params?.userId : +currentUserId}
- navigation={navigation}
- isPublicView={isPublicView}
- token={token ? token : null}
- />
- </ScrollView>
- <ReactModal
- isVisible={modalState.isModalVisible}
- onBackdropPress={() => closeModal('isModalVisible')}
- style={styles.modal}
- statusBarTranslucent={true}
- presentationStyle="overFullScreen"
- onModalHide={() => {
- if (shouldOpenWarningModal) {
- openModal('isWarningVisible');
- setShouldOpenWarningModal(false);
- }
- }}
- >
- <View style={styles.wrapper}>
- <TouchableOpacity
- style={styles.btnModalEdit}
- onPress={() => {
- closeModal('isModalVisible');
- setShouldOpenWarningModal(true);
- }}
- >
- <Text style={styles.btnModalEditText}>Unfriend</Text>
- <View style={{ transform: 'rotate(180deg)' }}>
- <ChevronIcon fill={Colors.DARK_BLUE} height={11} />
- </View>
- </TouchableOpacity>
- </View>
- </ReactModal>
- <WarningModal
- type={'confirm'}
- isVisible={modalState.isWarningVisible}
- message={`Are you sure you want to unfriend ${data.user_data.first_name} ${data.user_data.last_name}?`}
- action={handleUpdateFriendStatus}
- onClose={() => closeModal('isWarningVisible')}
- title=""
- />
- </PageWrapper>
- );
- };
- export default ProfileScreen;
|