aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-03-26 15:33:37 -0400
committerIvan Chen <ivan@tagg.id>2021-03-26 15:33:37 -0400
commit9be7248ba54eeb2ad4d19edd4c01ee736b58bfcd (patch)
tree6f66b86bbe9adaffb7d866b22a89e0e3f78f26a3
parent883a6c51d4c3e442df5e6c0f3dc6fada2f370f8e (diff)
parent99de9c8402f470ead242a81510dc2764ae7d9e66 (diff)
Merge branch 'master' into tma728-select-school-onboarding
# Conflicts: # src/services/UserProfileService.ts # src/types/types.ts
-rw-r--r--.circleci/config.yml15
-rw-r--r--src/assets/images/avatar-placeholder.pngbin2982 -> 0 bytes
-rw-r--r--src/assets/images/cover-placeholder.pngbin4117 -> 0 bytes
-rw-r--r--src/components/moments/IndividualMomentTitleBar.tsx9
-rw-r--r--src/components/moments/MomentPostHeader.tsx29
-rw-r--r--src/components/notifications/Notification.tsx45
-rw-r--r--src/components/profile/Avatar.tsx7
-rw-r--r--src/components/profile/Content.tsx12
-rw-r--r--src/components/profile/Cover.tsx11
-rw-r--r--src/components/search/SearchCategories.tsx18
-rw-r--r--src/constants/api.ts1
-rw-r--r--src/constants/constants.ts15
-rw-r--r--src/services/ExploreService.ts37
-rw-r--r--src/services/UserFriendsService.ts3
-rw-r--r--src/services/UserProfileService.ts130
-rw-r--r--src/store/actions/taggUsers.ts3
-rw-r--r--src/store/actions/user.ts7
-rw-r--r--src/store/actions/userX.ts83
-rw-r--r--src/store/initialStates.ts16
-rw-r--r--src/types/types.ts24
-rw-r--r--src/utils/friends.ts4
-rw-r--r--src/utils/users.ts24
22 files changed, 228 insertions, 265 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 8878e2e3..893711ad 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,7 +3,7 @@ version: 2.1
# Invoke the react-native orb.
orbs:
- rn: react-native-community/react-native@5.0.0
+ rn: react-native-community/react-native@5.1.0
# Define runnable jobs.
jobs:
@@ -13,8 +13,8 @@ jobs:
steps:
- checkout
- persist_to_workspace:
- root: .
paths: .
+ root: .
# Run linter, type-checker, and tests.
analyze_code:
executor: rn/linux_js
@@ -23,14 +23,14 @@ jobs:
at: .
- rn/yarn_install
- run:
- name: Run ESLint (`yarn lint`)
command: yarn lint
+ name: Run ESLint (`yarn lint`)
- run:
- name: Run TSC (`yarn type`)
command: yarn type
+ name: Run TSC (`yarn type`)
- run:
- name: Run Jest (`yarn test`)
command: yarn test
+ name: Run Jest (`yarn test`)
# Define workflows.
workflows:
@@ -39,12 +39,13 @@ workflows:
jobs:
- checkout_code
- analyze_code:
- requries: -checkout_code
+ requires:
+ - checkout_code
- rn/ios_build:
name: build_ios_release
project_path: ios/Frontend.xcodeproj
device: 'iPhone 11'
- build_configuration: Release
+ build_configuration: Debug
scheme: Frontend
requires:
- analyze_code
diff --git a/src/assets/images/avatar-placeholder.png b/src/assets/images/avatar-placeholder.png
deleted file mode 100644
index 313f384e..00000000
--- a/src/assets/images/avatar-placeholder.png
+++ /dev/null
Binary files differ
diff --git a/src/assets/images/cover-placeholder.png b/src/assets/images/cover-placeholder.png
deleted file mode 100644
index 141167d1..00000000
--- a/src/assets/images/cover-placeholder.png
+++ /dev/null
Binary files differ
diff --git a/src/components/moments/IndividualMomentTitleBar.tsx b/src/components/moments/IndividualMomentTitleBar.tsx
index 88e0c308..79453ade 100644
--- a/src/components/moments/IndividualMomentTitleBar.tsx
+++ b/src/components/moments/IndividualMomentTitleBar.tsx
@@ -29,14 +29,14 @@ const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
- justifyContent: 'center',
+ justifyContent: 'flex-start',
height: '5%',
},
headerContainer: {
- flexShrink: 1,
- marginLeft: '11%',
+ width: '80%',
},
header: {
+ textAlign: 'center',
color: 'white',
fontSize: normalize(18),
fontWeight: '700',
@@ -44,10 +44,9 @@ const styles = StyleSheet.create({
letterSpacing: normalize(1.3),
},
closeButton: {
- position: 'absolute',
height: '50%',
aspectRatio: 1,
- left: '3%',
+ left: '8%',
},
});
diff --git a/src/components/moments/MomentPostHeader.tsx b/src/components/moments/MomentPostHeader.tsx
index aad776e8..ff324c4a 100644
--- a/src/components/moments/MomentPostHeader.tsx
+++ b/src/components/moments/MomentPostHeader.tsx
@@ -1,12 +1,19 @@
import React, {useState} from 'react';
-import {StyleSheet, Text, View, ViewProps} from 'react-native';
+import {
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+ ViewProps,
+} from 'react-native';
import {MomentMoreInfoDrawer} from '../profile';
import {loadUserMoments} from '../../store/actions';
-import {useDispatch, useSelector} from 'react-redux';
+import {useDispatch, useSelector, useStore} from 'react-redux';
import {ScreenType} from '../../types';
import Avatar from '../profile/Avatar';
import {useNavigation} from '@react-navigation/native';
import {RootState} from '../../store/rootReducer';
+import {fetchUserX, userXInStore} from '../../utils';
interface MomentPostHeaderProps extends ViewProps {
userXId?: string;
@@ -24,22 +31,36 @@ const MomentPostHeader: React.FC<MomentPostHeaderProps> = ({
}) => {
const [drawerVisible, setDrawerVisible] = useState(false);
const dispatch = useDispatch();
+ const state: RootState = useStore().getState();
const navigation = useNavigation();
const {userId: loggedInUserId, username: loggedInUserName} = useSelector(
(state: RootState) => state.user.user,
);
const isOwnProfile = loggedInUserName === username;
+ const navigateToProfile = async () => {
+ if (userXId && !userXInStore(state, screenType, userXId)) {
+ await fetchUserX(
+ dispatch,
+ {userId: userXId, username: username},
+ screenType,
+ );
+ }
+ navigation.navigate('Profile', {
+ userXId: isOwnProfile ? undefined : userXId,
+ screenType,
+ });
+ };
return (
<View style={[styles.container, style]}>
- <View style={styles.header}>
+ <TouchableOpacity onPress={navigateToProfile} style={styles.header}>
<Avatar
style={styles.avatar}
userXId={userXId}
screenType={screenType}
/>
<Text style={styles.headerText}>{username}</Text>
- </View>
+ </TouchableOpacity>
<MomentMoreInfoDrawer
isOpen={drawerVisible}
setIsOpen={setDrawerVisible}
diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx
index c8a8aa06..8143e396 100644
--- a/src/components/notifications/Notification.tsx
+++ b/src/components/notifications/Notification.tsx
@@ -205,11 +205,22 @@ const Notification: React.FC<NotificationProps> = (props) => {
dispatch(loadUserNotifications());
};
+ const isOwnProfile = id === loggedInUser.userId;
+ const navigateToProfile = async () => {
+ if (!userXInStore(state, screenType, id)) {
+ await fetchUserX(dispatch, {userId: id, username: username}, screenType);
+ }
+ navigation.navigate('Profile', {
+ userXId: isOwnProfile ? undefined : id,
+ screenType,
+ });
+ };
+
const renderContent = () => (
- <TouchableWithoutFeedback
- style={styles.container}
- onPress={onNotificationTap}>
- <View style={styles.avatarContainer}>
+ <View style={styles.container}>
+ <TouchableWithoutFeedback
+ onPress={navigateToProfile}
+ style={styles.avatarContainer}>
<Image
style={styles.avatar}
source={
@@ -218,12 +229,16 @@ const Notification: React.FC<NotificationProps> = (props) => {
: require('../../assets/images/avatar-placeholder.png')
}
/>
- </View>
+ </TouchableWithoutFeedback>
<View style={styles.contentContainer}>
- <Text style={styles.actorName}>
- {first_name} {last_name}
- </Text>
- <Text>{verbage}</Text>
+ <TouchableWithoutFeedback onPress={navigateToProfile}>
+ <Text style={styles.actorName}>
+ {first_name} {last_name}
+ </Text>
+ </TouchableWithoutFeedback>
+ <TouchableWithoutFeedback onPress={onNotificationTap}>
+ <Text>{verbage}</Text>
+ </TouchableWithoutFeedback>
</View>
{notification_type === 'FRD_REQ' && (
<View style={styles.buttonsContainer}>
@@ -238,9 +253,13 @@ const Notification: React.FC<NotificationProps> = (props) => {
notification_type === 'MOM_3+' ||
notification_type === 'MOM_FRIEND') &&
notification_object && (
- <Image style={styles.moment} source={{uri: momentURI}} />
+ <TouchableWithoutFeedback
+ style={styles.moment}
+ onPress={onNotificationTap}>
+ <Image style={styles.imageFlex} source={{uri: momentURI}} />
+ </TouchableWithoutFeedback>
)}
- </TouchableWithoutFeedback>
+ </View>
);
return unread ? (
@@ -284,7 +303,6 @@ const styles = StyleSheet.create({
fontWeight: '700',
},
moment: {
- position: 'absolute',
height: 42,
width: 42,
right: '5%',
@@ -292,6 +310,9 @@ const styles = StyleSheet.create({
buttonsContainer: {
height: '80%',
},
+ imageFlex: {
+ flex: 1,
+ },
});
export default Notification;
diff --git a/src/components/profile/Avatar.tsx b/src/components/profile/Avatar.tsx
index ba4ec36c..5d677983 100644
--- a/src/components/profile/Avatar.tsx
+++ b/src/components/profile/Avatar.tsx
@@ -19,11 +19,8 @@ const Avatar: React.FC<AvatarProps> = ({style, screenType, userXId}) => {
return (
<Image
style={[styles.image, style]}
- source={
- avatar
- ? {uri: avatar}
- : require('../../assets/images/avatar-placeholder.png')
- }
+ defaultSource={require('../../assets/images/avatar-placeholder.png')}
+ source={{uri: avatar}}
/>
);
};
diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx
index d4c50d5c..1a5a205c 100644
--- a/src/components/profile/Content.tsx
+++ b/src/components/profile/Content.tsx
@@ -109,9 +109,10 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => {
const [isStageOnePromptClosed, setIsStageOnePromptClosed] = useState<boolean>(
false,
);
- const [isStageThreePromptClosed, setIsStageThreePromptClosed] = useState<
- boolean
- >(false);
+ const [
+ isStageThreePromptClosed,
+ setIsStageThreePromptClosed,
+ ] = useState<boolean>(false);
const onRefresh = useCallback(() => {
const refrestState = async () => {
@@ -308,7 +309,10 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => {
isBlocked,
}}
/>
- <TaggsBar {...{y, profileBodyHeight, userXId, screenType}} />
+ <TaggsBar
+ {...{y, profileBodyHeight, userXId, screenType}}
+ whiteRing={undefined}
+ />
<View style={styles.momentsContainer}>
{userXId && moments.length === 0 && (
<View style={styles.plusIconContainer}>
diff --git a/src/components/profile/Cover.tsx b/src/components/profile/Cover.tsx
index a03ef123..b7502cff 100644
--- a/src/components/profile/Cover.tsx
+++ b/src/components/profile/Cover.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {Image, StyleSheet, View} from 'react-native';
-import {IMAGE_WIDTH, COVER_HEIGHT, IMAGE_HEIGHT} from '../../constants';
import {useSelector} from 'react-redux';
+import {COVER_HEIGHT, IMAGE_WIDTH} from '../../constants';
import {RootState} from '../../store/rootreducer';
import {ScreenType} from '../../types';
@@ -10,7 +10,7 @@ interface CoverProps {
screenType: ScreenType;
}
const Cover: React.FC<CoverProps> = ({userXId, screenType}) => {
- const {cover = ''} = userXId
+ const {cover} = userXId
? useSelector((state: RootState) => state.userX[screenType][userXId])
: useSelector((state: RootState) => state.user);
@@ -18,11 +18,8 @@ const Cover: React.FC<CoverProps> = ({userXId, screenType}) => {
<View style={[styles.container]}>
<Image
style={styles.image}
- source={
- cover
- ? {uri: cover}
- : require('../../assets/images/cover-placeholder.png')
- }
+ defaultSource={require('../../assets/images/cover-placeholder.png')}
+ source={{uri: cover}}
/>
</View>
);
diff --git a/src/components/search/SearchCategories.tsx b/src/components/search/SearchCategories.tsx
index 4bae27c2..c747b34f 100644
--- a/src/components/search/SearchCategories.tsx
+++ b/src/components/search/SearchCategories.tsx
@@ -73,23 +73,5 @@ const styles = StyleSheet.create({
flexWrap: 'wrap',
justifyContent: 'space-evenly',
},
- buttonContainer: {
- backgroundColor: 'transparent',
- width: 158,
- height: 37,
- borderRadius: 20,
- borderColor: 'transparent',
- borderWidth: 1,
- flexDirection: 'row',
- alignContent: 'center',
- justifyContent: 'center',
- },
- buttonText: {
- fontWeight: '400',
- fontSize: 15,
- lineHeight: 17.9,
- alignSelf: 'center',
- color: 'white',
- },
});
export default SearchCategories;
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 1e2e887a..6afdf384 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -9,6 +9,7 @@ export const REGISTER_ENDPOINT: string = API_URL + 'register/';
export const EDIT_PROFILE_ENDPOINT: string = API_URL + 'edit-profile/';
export const SEND_OTP_ENDPOINT: string = API_URL + 'send-otp/';
export const VERIFY_OTP_ENDPOINT: string = API_URL + 'verify-otp/';
+export const USER_PROFILE_ENDPOINT: string = API_URL + 'profile/';
export const PROFILE_INFO_ENDPOINT: string = API_URL + 'user-profile-info/';
export const HEADER_PHOTO_ENDPOINT: string = API_URL + 'header-pic/';
export const PROFILE_PHOTO_ENDPOINT: string = API_URL + 'profile-pic/';
diff --git a/src/constants/constants.ts b/src/constants/constants.ts
index 6b513f4e..d24e352e 100644
--- a/src/constants/constants.ts
+++ b/src/constants/constants.ts
@@ -1,6 +1,6 @@
import {ReactText} from 'react';
-import {BackgroundGradientType, ExploreSectionType} from './../types/';
-import {SCREEN_WIDTH, SCREEN_HEIGHT, isIPhoneX, normalize} from '../utils';
+import {isIPhoneX, normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../utils';
+import {BackgroundGradientType} from './../types/';
export const CHIN_HEIGHT = 34;
@@ -182,17 +182,6 @@ export const MOMENT_CATEGORY_BG_COLORS: string[] = [
'#4E7175',
];
-// order matters, this decides the order which it displays
-export const EXPLORE_SECTION_TITLES: ExploreSectionType[] = [
- 'New to Tagg',
- 'People You May Know',
- 'Trending on Tagg',
- "Brown '24",
- "Brown '23",
- "Brown '22",
- "Brown '21",
-];
-
export const SP_WIDTH = 375;
export const SP_HEIGHT = 812;
diff --git a/src/services/ExploreService.ts b/src/services/ExploreService.ts
index 07af91ad..44df8056 100644
--- a/src/services/ExploreService.ts
+++ b/src/services/ExploreService.ts
@@ -4,12 +4,7 @@ import {
DISCOVER_ENDPOINT,
SEARCH_BUTTONS_ENDPOPINT,
} from '../constants';
-import {EMPTY_PROFILE_PREVIEW_LIST} from '../store/initialStates';
-import {
- ExploreSectionType,
- ProfilePreviewType,
- SearchCategoryType,
-} from '../types';
+import {ProfilePreviewType, SearchCategoryType} from '../types';
export const getAllTaggUsers = async (token: string) => {
try {
@@ -38,36 +33,6 @@ export const getAllTaggUsers = async (token: string) => {
}
};
-export const getAllExploreSections = async () => {
- try {
- const token = await AsyncStorage.getItem('token');
- const response = await fetch(DISCOVER_ENDPOINT, {
- method: 'GET',
- headers: {
- Authorization: 'Token ' + token,
- },
- });
- if (response.status !== 200) {
- return EMPTY_PROFILE_PREVIEW_LIST;
- }
- const data = await response.json();
- // TODO (if we return to original explore format): get keys from backend API
- const exploreSections: Record<ExploreSectionType, ProfilePreviewType[]> = {
- 'New to Tagg': data.categories.new_to_tagg,
- 'People You May Know': data.categories.people_you_may_know,
- 'Trending on Tagg': data.categories.trending_on_tagg,
- "Brown '21": data.categories.brown_21,
- "Brown '22": data.categories.brown_22,
- "Brown '23": data.categories.brown_23,
- "Brown '24": data.categories.brown_24,
- };
-
- return exploreSections;
- } catch (error) {
- console.log('Unable to fetch explore data');
- }
-};
-
export const getDiscoverUsers = async (categoryName: string) => {
try {
const token = await AsyncStorage.getItem('token');
diff --git a/src/services/UserFriendsService.ts b/src/services/UserFriendsService.ts
index c36cdaa7..da39380f 100644
--- a/src/services/UserFriendsService.ts
+++ b/src/services/UserFriendsService.ts
@@ -24,12 +24,11 @@ export const loadFriends = async (userId: string, token: string) => {
if (response.status === 200) {
const body = await response.json();
return body;
- } else {
- throw new Error(await response.json());
}
} catch (error) {
console.log(error);
}
+ return [];
};
export const friendOrUnfriendUser = async (
diff --git a/src/services/UserProfileService.ts b/src/services/UserProfileService.ts
index a5b42814..085787c3 100644
--- a/src/services/UserProfileService.ts
+++ b/src/services/UserProfileService.ts
@@ -1,7 +1,6 @@
import AsyncStorage from '@react-native-community/async-storage';
import moment from 'moment';
import {Alert} from 'react-native';
-import RNFetchBlob from 'rn-fetch-blob';
import {
EDIT_PROFILE_ENDPOINT,
GET_FB_POSTS_ENDPOINT,
@@ -11,10 +10,10 @@ import {
PASSWORD_RESET_ENDPOINT,
PROFILE_INFO_ENDPOINT,
PROFILE_PHOTO_ENDPOINT,
- PROFILE_PHOTO_THUMBNAIL_ENDPOINT,
REGISTER_ENDPOINT,
SEND_OTP_ENDPOINT,
TAGG_CUSTOMER_SUPPORT,
+ USER_PROFILE_ENDPOINT,
VERIFY_OTP_ENDPOINT,
} from '../constants';
import {
@@ -28,7 +27,7 @@ import {
SUCCESS_PWD_RESET,
SUCCESS_VERIFICATION_CODE_SENT,
} from '../constants/strings';
-import {SocialAccountType} from '../types';
+import {ProfileInfoType, ProfileType, SocialAccountType} from '../types';
export const loadProfileInfo = async (token: string, userId: string) => {
try {
@@ -40,35 +39,11 @@ export const loadProfileInfo = async (token: string, userId: string) => {
});
const status = response.status;
if (status === 200) {
- const info = await response.json();
- let {
- name,
- biography,
- website,
- birthday,
- gender,
- snapchat,
- tiktok,
- university_class,
- profile_completion_stage,
- suggested_people_linked,
- friendship_status,
- friendship_requester_id,
- } = info;
- birthday = birthday && moment(birthday).format('YYYY-MM-DD');
+ const data: ProfileInfoType = await response.json();
+ const birthday = data.birthday;
return {
- name,
- biography,
- website,
- birthday,
- gender,
- snapchat,
- tiktok,
- university_class,
- profile_completion_stage,
- suggested_people_linked,
- friendship_status,
- friendship_requester_id,
+ ...data,
+ birthday: birthday && moment(birthday).format('YYYY-MM-DD'),
};
} else {
throw 'Unable to load profile data';
@@ -78,43 +53,22 @@ export const loadProfileInfo = async (token: string, userId: string) => {
}
};
-export const loadAvatar = async (userId: string, thumbnail: boolean) => {
- try {
- const token = await AsyncStorage.getItem('token');
- const url = thumbnail
- ? PROFILE_PHOTO_THUMBNAIL_ENDPOINT
- : PROFILE_PHOTO_ENDPOINT;
- const response = await RNFetchBlob.config({
- fileCache: true,
- appendExt: 'jpg',
- }).fetch('GET', url + `${userId}/`, {
- Authorization: 'Token ' + token,
- });
- const status = response.info().status;
- if (status === 200) {
- return response.path();
- } else {
- return '';
- }
- } catch (error) {
- console.log(error);
- return '';
- }
-};
-
-export const loadCover = async (token: string, userId: string) => {
+export const getProfilePic = async (
+ token: string,
+ userId: string,
+ type: 'profile' | 'header',
+) => {
try {
- let response = await RNFetchBlob.config({
- fileCache: true,
- appendExt: 'jpg',
- }).fetch('GET', HEADER_PHOTO_ENDPOINT + `${userId}/`, {
- Authorization: 'Token ' + token,
+ const url =
+ type === 'profile' ? PROFILE_PHOTO_ENDPOINT : HEADER_PHOTO_ENDPOINT;
+ const response = await fetch(url + `${userId}/`, {
+ method: 'GET',
+ headers: {
+ Authorization: 'Token ' + token,
+ },
});
- const status = response.info().status;
- if (status === 200) {
- return response.path();
- } else {
- return '';
+ if (response.status === 200) {
+ return (await response.json()).url;
}
} catch (error) {
console.log(error);
@@ -130,8 +84,11 @@ const integratedSocialPostsEndpoints: {[social: string]: string} = {
export const loadSocialPosts: (
userId: string,
socialType: string,
-) => Promise<SocialAccountType> = async (userId, socialType) => {
- const token = await AsyncStorage.getItem('token');
+ token?: string,
+) => Promise<SocialAccountType> = async (userId, socialType, token) => {
+ if (!token) {
+ token = (await AsyncStorage.getItem('token')) ?? '';
+ }
const endpoint = integratedSocialPostsEndpoints[socialType];
const accountData: SocialAccountType = {};
accountData.posts = [];
@@ -340,19 +297,19 @@ export const sendRegister = async (
password: string,
) => {
try {
- const form = new FormData()
- form.append('first_name', firstName)
- form.append('last_name', lastName)
- form.append('email', email)
- form.append('phone_number', phone)
- form.append('username', username)
- form.append('password', password)
+ const form = new FormData();
+ form.append('first_name', firstName);
+ form.append('last_name', lastName);
+ form.append('email', email);
+ form.append('phone_number', phone);
+ form.append('username', username);
+ form.append('password', password);
const response = await fetch(REGISTER_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
- body: form
+ body: form,
});
return response;
} catch (error) {
@@ -361,6 +318,27 @@ export const sendRegister = async (
}
};
+export const fetchUserProfile = async (userId: string, token?: string) => {
+ try {
+ if (!token) {
+ token = (await AsyncStorage.getItem('token')) ?? '';
+ }
+ const response = await fetch(USER_PROFILE_ENDPOINT + userId + '/', {
+ method: 'GET',
+ headers: {
+ Authorization: 'Token ' + token,
+ },
+ });
+ if (response.status === 200) {
+ const data: ProfileType = await response.json();
+ return data;
+ }
+ } catch (error) {
+ console.log(error);
+ return undefined;
+ }
+};
+
export const patchEditProfile = async (form: FormData, userId: string) => {
const endpoint = EDIT_PROFILE_ENDPOINT + `${userId}/`;
try {
diff --git a/src/store/actions/taggUsers.ts b/src/store/actions/taggUsers.ts
index 72ce848b..0cd94e92 100644
--- a/src/store/actions/taggUsers.ts
+++ b/src/store/actions/taggUsers.ts
@@ -1,5 +1,5 @@
import {Action, ThunkAction} from '@reduxjs/toolkit';
-import {getAllExploreSections, loadRecentlySearchedUsers} from '../../services';
+import {loadRecentlySearchedUsers} from '../../services';
import {taggUsersFetched} from '../reducers';
import {RootState} from '../rootReducer';
@@ -11,7 +11,6 @@ export const loadRecentlySearched = (): ThunkAction<
> => async (dispatch) => {
try {
const recentSearches = await loadRecentlySearchedUsers();
- getAllExploreSections();
dispatch({
type: taggUsersFetched.type,
payload: {recentSearches},
diff --git a/src/store/actions/user.ts b/src/store/actions/user.ts
index 4f1da47c..46f96d9a 100644
--- a/src/store/actions/user.ts
+++ b/src/store/actions/user.ts
@@ -1,7 +1,6 @@
import {Action, ThunkAction} from '@reduxjs/toolkit';
import {
- loadAvatar,
- loadCover,
+ getProfilePic,
loadProfileInfo,
sendSuggestedPeopleLinked,
} from '../../services';
@@ -43,8 +42,8 @@ export const loadUserData = (
const token = await getTokenOrLogout(dispatch);
const [profile, avatar, cover] = await Promise.all([
loadProfileInfo(token, user.userId),
- loadAvatar(user.userId, false),
- loadCover(token, user.userId),
+ getProfilePic(token, user.userId, 'profile'),
+ getProfilePic(token, user.userId, 'header'),
]);
dispatch({
type: userDetailsFetched.type,
diff --git a/src/store/actions/userX.ts b/src/store/actions/userX.ts
index 07bea678..f32a4d8f 100644
--- a/src/store/actions/userX.ts
+++ b/src/store/actions/userX.ts
@@ -1,28 +1,27 @@
-import {userXInStore} from './../../utils/';
-import {getTokenOrLogout, loadAllSocialsForUser} from './../../utils';
-import {UserType, ScreenType} from '../../types/types';
-import {RootState} from '../rootReducer';
import {Action, ThunkAction} from '@reduxjs/toolkit';
+import moment from 'moment';
import {
- userXRequested,
+ fetchUserProfile,
+ loadFriends,
+ loadMoments,
+ loadProfileInfo,
+} from '../../services';
+import {ScreenType, UserType} from '../../types/types';
+import {
+ resetScreen,
userXAvatarFetched,
- userXFriendsFetched,
userXCoverFetched,
+ userXFriendsFetched,
+ userXMomentCategoriesFetched,
userXMomentsFetched,
userXProfileFetched,
+ userXRequested,
userXSocialsFetched,
userXUserFetched,
- userXMomentCategoriesFetched,
- resetScreen,
} from '../reducers';
-import {
- loadProfileInfo,
- loadAvatar,
- loadCover,
- loadFriends,
- loadMomentCategories,
- loadMoments,
-} from '../../services';
+import {RootState} from '../rootReducer';
+import {getTokenOrLogout, loadAllSocialsForUser} from './../../utils';
+import {userXInStore} from './../../utils/';
export const loadUserX = (
user: UserType,
@@ -38,30 +37,40 @@ export const loadUserX = (
payload: {screenType, userId, user},
});
const token = await getTokenOrLogout(dispatch);
- loadProfileInfo(token, userId).then((data) => {
- dispatch({
- type: userXProfileFetched.type,
- payload: {screenType, userId, data},
- });
+ fetchUserProfile(userId, token).then((profile) => {
+ if (profile) {
+ const birthday = profile.profile_info.birthday;
+ dispatch({
+ type: userXProfileFetched.type,
+ payload: {
+ screenType,
+ userId,
+ data: {
+ ...profile.profile_info,
+ birthday: birthday && moment(birthday).format('YYYY-MM-DD'),
+ },
+ },
+ });
+ dispatch({
+ type: userXAvatarFetched.type,
+ payload: {screenType, userId, data: profile.profile_pic},
+ });
+ dispatch({
+ type: userXCoverFetched.type,
+ payload: {screenType, userId, data: profile.header_pic},
+ });
+ dispatch({
+ type: userXMomentCategoriesFetched.type,
+ payload: {screenType, userId, data: profile.moment_categories},
+ });
+ }
});
- loadAllSocialsForUser(userId).then((data) =>
+ loadAllSocialsForUser(userId, token).then((data) =>
dispatch({
type: userXSocialsFetched.type,
payload: {screenType, userId, data},
}),
);
- loadAvatar(userId, false).then((data) =>
- dispatch({
- type: userXAvatarFetched.type,
- payload: {screenType, userId, data},
- }),
- );
- loadCover(token, userId).then((data) =>
- dispatch({
- type: userXCoverFetched.type,
- payload: {screenType, userId, data},
- }),
- );
loadFriends(userId, token).then((data) =>
dispatch({
type: userXFriendsFetched.type,
@@ -74,12 +83,6 @@ export const loadUserX = (
payload: {screenType, userId, data},
}),
);
- loadMomentCategories(userId, token).then((data) => {
- dispatch({
- type: userXMomentCategoriesFetched.type,
- payload: {screenType, userId, data},
- });
- });
} catch (error) {
console.log(error);
}
diff --git a/src/store/initialStates.ts b/src/store/initialStates.ts
index b43e4a1d..47ab8f39 100644
--- a/src/store/initialStates.ts
+++ b/src/store/initialStates.ts
@@ -1,17 +1,16 @@
import {CommentThreadType} from './../types/types';
import {
- ExploreSectionType,
MomentType,
NotificationType,
ProfilePreviewType,
- ProfileType,
+ ProfileInfoType,
ScreenType,
SocialAccountType,
UserType,
UserXType,
} from '../types';
-export const NO_PROFILE: ProfileType = {
+export const NO_PROFILE: ProfileInfoType = {
biography: '',
website: '',
name: '',
@@ -26,6 +25,7 @@ export const NO_PROFILE: ProfileType = {
tiktok: '',
friendship_status: 'no_record',
friendship_requester_id: '',
+ is_private: true,
};
export const EMPTY_MOMENTS_LIST = <MomentType[]>[];
@@ -41,9 +41,9 @@ export const EMPTY_PROFILE_PREVIEW_LIST = <ProfilePreviewType[]>[];
export const NO_USER_DATA = {
user: <UserType>NO_USER,
- profile: <ProfileType>NO_PROFILE,
- avatar: <string | null>'',
- cover: <string | null>'',
+ profile: <ProfileInfoType>NO_PROFILE,
+ avatar: <string | undefined>undefined,
+ cover: <string | undefined>undefined,
isOnboardedUser: false,
newVersionAvailable: false,
newNotificationReceived: false,
@@ -98,8 +98,8 @@ export const EMPTY_USER_X = <UserXType>{
socialAccounts: NO_SOCIAL_ACCOUNTS,
user: NO_USER,
profile: NO_PROFILE,
- avatar: '',
- cover: '',
+ avatar: undefined,
+ cover: undefined,
};
/**
diff --git a/src/types/types.ts b/src/types/types.ts
index 412d9000..80e404e6 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -27,6 +27,14 @@ export enum UniversityType {
}
export interface ProfileType {
+ profile_pic: string;
+ header_pic: string;
+ profile_info: ProfileInfoType;
+ moment_categories: string[];
+ linked_socials: string[];
+}
+
+export interface ProfileInfoType {
name: string;
biography: string;
website: string;
@@ -40,6 +48,7 @@ export interface ProfileType {
tiktok: string;
friendship_status: FriendshipStatusType;
friendship_requester_id: string;
+ is_private: boolean;
}
export interface SocialAccountType {
@@ -131,15 +140,6 @@ export enum ScreenType {
SuggestedPeople,
}
-export type ExploreSectionType =
- | 'People You May Know'
- | 'New to Tagg'
- | 'Trending on Tagg'
- | "Brown '21"
- | "Brown '22"
- | "Brown '23"
- | "Brown '24";
-
/**
* Redux store to have a Record of ScreenType (Search, Profile, Home etc) mapped to
* A Record of userIXd mapped to UserXType
@@ -153,9 +153,9 @@ export interface UserXType {
socialAccounts: Record<string, SocialAccountType>;
momentCategories: string[];
user: UserType;
- profile: ProfileType;
- avatar: string;
- cover: string;
+ profile: ProfileInfoType;
+ avatar: string | undefined;
+ cover: string | undefined;
}
/**
diff --git a/src/utils/friends.ts b/src/utils/friends.ts
index 55d65170..5b0ded8f 100644
--- a/src/utils/friends.ts
+++ b/src/utils/friends.ts
@@ -1,7 +1,7 @@
// Handles click on friend/requested/unfriend button
import {RootState} from '../store/rootReducer';
-import {ProfilePreviewType, ProfileType, ScreenType, UserType} from '../types';
+import {ProfilePreviewType, ProfileInfoType, ScreenType, UserType} from '../types';
import {AppDispatch} from '../store/configureStore';
import {
addFriend,
@@ -25,7 +25,7 @@ import {getUserAsProfilePreviewType} from './users';
export const handleFriendUnfriend = async (
screenType: ScreenType,
user: UserType,
- profile: ProfileType,
+ profile: ProfileInfoType,
dispatch: AppDispatch,
state: RootState,
loggedInUser: UserType,
diff --git a/src/utils/users.ts b/src/utils/users.ts
index 82bcb309..d5e44b36 100644
--- a/src/utils/users.ts
+++ b/src/utils/users.ts
@@ -20,7 +20,7 @@ import {RootState} from './../store/rootReducer';
import {
ProfilePreviewType,
CategoryPreviewType,
- ProfileType,
+ ProfileInfoType,
ScreenType,
UserType,
} from './../types/types';
@@ -103,13 +103,22 @@ export const userXInStore = (
* Abstracted the code to laod all socials out.
* @param userId userId for whom socials should be fetched
*/
-export const loadAllSocialsForUser = async (userId: string) => {
+export const loadAllSocialsForUser = async (userId: string, token?: string) => {
+ if (!token) {
+ token = (await AsyncStorage.getItem('token')) ?? '';
+ }
let socials = NO_SOCIAL_ACCOUNTS;
try {
- let socialNeedsUpdate = INTEGRATED_SOCIAL_LIST;
- for (let socialType of socialNeedsUpdate) {
- const social = await loadSocialPosts(userId, socialType);
- socials = {...socials, [socialType]: social};
+ const fetchedSocials = await Promise.all(
+ INTEGRATED_SOCIAL_LIST.map((socialType) =>
+ loadSocialPosts(userId, socialType, token).then((data) => ({
+ key: socialType,
+ data,
+ })),
+ ),
+ );
+ for (const fetchedSocial of fetchedSocials) {
+ socials = {...socials, [fetchedSocial.key]: fetchedSocial.data};
}
return socials;
} catch (error) {
@@ -137,7 +146,7 @@ export const getTokenOrLogout = async (dispatch: Function): Promise<string> => {
*/
export const getUserAsProfilePreviewType = (
passedInUser: UserType,
- passedInProfile: ProfileType,
+ passedInProfile: ProfileInfoType,
): ProfilePreviewType => {
const fullName = passedInProfile.name.split(' ');
return {
@@ -165,4 +174,3 @@ export const defaultUserProfile = () => {
const defaultImage = require('../assets/images/avatar-placeholder.png');
return defaultImage;
};
-