aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/assets/images/bwbadges.pngbin0 -> 528 bytes
-rw-r--r--src/assets/images/bwbadges@2x.pngbin0 -> 991 bytes
-rw-r--r--src/assets/images/bwbadges@3x.pngbin0 -> 1438 bytes
-rw-r--r--src/assets/images/search.pngbin0 -> 354 bytes
-rw-r--r--src/assets/images/search@2x.pngbin0 -> 643 bytes
-rw-r--r--src/assets/images/search@3x.pngbin0 -> 901 bytes
-rw-r--r--src/components/profile/ProfilePreview.tsx35
-rw-r--r--src/components/search/ExploreSection.tsx2
-rw-r--r--src/components/search/RecentSearches.tsx9
-rw-r--r--src/components/search/SearchResultCell.tsx187
-rw-r--r--src/components/search/SearchResultList.tsx93
-rw-r--r--src/components/search/SearchResultsBackground.tsx9
-rw-r--r--src/components/search/index.ts1
-rw-r--r--src/constants/api.ts2
-rw-r--r--src/constants/strings.ts1
-rw-r--r--src/screens/search/SearchScreen.tsx72
-rw-r--r--src/screens/search/mock.ts118
-rw-r--r--src/services/SearchService.ts22
-rw-r--r--src/services/index.ts1
-rw-r--r--src/utils/users.ts37
20 files changed, 516 insertions, 73 deletions
diff --git a/src/assets/images/bwbadges.png b/src/assets/images/bwbadges.png
new file mode 100644
index 00000000..3a337775
--- /dev/null
+++ b/src/assets/images/bwbadges.png
Binary files differ
diff --git a/src/assets/images/bwbadges@2x.png b/src/assets/images/bwbadges@2x.png
new file mode 100644
index 00000000..60c2f995
--- /dev/null
+++ b/src/assets/images/bwbadges@2x.png
Binary files differ
diff --git a/src/assets/images/bwbadges@3x.png b/src/assets/images/bwbadges@3x.png
new file mode 100644
index 00000000..874c0c4d
--- /dev/null
+++ b/src/assets/images/bwbadges@3x.png
Binary files differ
diff --git a/src/assets/images/search.png b/src/assets/images/search.png
new file mode 100644
index 00000000..ba9906ba
--- /dev/null
+++ b/src/assets/images/search.png
Binary files differ
diff --git a/src/assets/images/search@2x.png b/src/assets/images/search@2x.png
new file mode 100644
index 00000000..fa133ae1
--- /dev/null
+++ b/src/assets/images/search@2x.png
Binary files differ
diff --git a/src/assets/images/search@3x.png b/src/assets/images/search@3x.png
new file mode 100644
index 00000000..3ea4ce15
--- /dev/null
+++ b/src/assets/images/search@3x.png
Binary files differ
diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx
index 0021b1c6..f08335a1 100644
--- a/src/components/profile/ProfilePreview.tsx
+++ b/src/components/profile/ProfilePreview.tsx
@@ -16,6 +16,7 @@ import {loadImageFromURL} from '../../services';
import {RootState} from '../../store/rootreducer';
import {PreviewType, ProfilePreviewType, ScreenType} from '../../types';
import {
+ addUserToRecentlyViewed,
checkIfUserIsBlocked,
fetchUserX,
isIPhoneX,
@@ -89,39 +90,7 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({
return;
}
if (previewType !== 'Comment') {
- const jsonValue = await AsyncStorage.getItem(
- '@recently_searched_users',
- );
- let recentlySearchedList =
- jsonValue != null ? JSON.parse(jsonValue) : null;
- if (recentlySearchedList) {
- if (recentlySearchedList.length > 0) {
- if (
- recentlySearchedList.some(
- (saved_user: ProfilePreviewType) => saved_user.id === id,
- )
- ) {
- console.log('User already in recently searched.');
- } else {
- if (recentlySearchedList.length >= 10) {
- recentlySearchedList.pop();
- }
- recentlySearchedList.unshift(user);
- }
- }
- } else {
- recentlySearchedList = [user];
- }
-
- try {
- let recentlySearchedListString = JSON.stringify(recentlySearchedList);
- await AsyncStorage.setItem(
- '@recently_searched_users',
- recentlySearchedListString,
- );
- } catch (e) {
- console.log(e);
- }
+ await addUserToRecentlyViewed(user)
}
const userXId =
diff --git a/src/components/search/ExploreSection.tsx b/src/components/search/ExploreSection.tsx
index 025c8c3c..e888370e 100644
--- a/src/components/search/ExploreSection.tsx
+++ b/src/components/search/ExploreSection.tsx
@@ -14,7 +14,7 @@ interface ExploreSectionProps {
users: ProfilePreviewType[];
}
const ExploreSection: React.FC<ExploreSectionProps> = ({title, users}) => {
- return users.length !== 0 ? (
+ return users && users.length !== 0 ? (
<View style={styles.container}>
<Text style={styles.header}>{title}</Text>
<FlatList
diff --git a/src/components/search/RecentSearches.tsx b/src/components/search/RecentSearches.tsx
index bebf6bcf..6fb9fca9 100644
--- a/src/components/search/RecentSearches.tsx
+++ b/src/components/search/RecentSearches.tsx
@@ -5,10 +5,12 @@ import {
TouchableOpacity,
StyleSheet,
TouchableOpacityProps,
+ ScrollView,
} from 'react-native';
import {PreviewType, ProfilePreviewType, ScreenType} from '../../types';
import {TAGG_LIGHT_BLUE} from '../../constants';
import SearchResults from './SearchResults';
+import {SCREEN_HEIGHT} from '../../utils';
interface RecentSearchesProps extends TouchableOpacityProps {
sectionTitle: PreviewType;
@@ -21,7 +23,9 @@ interface RecentSearchesProps extends TouchableOpacityProps {
*/
const RecentSearches: React.FC<RecentSearchesProps> = (props) => {
return (
- <View style={styles.mainContainer}>
+ <ScrollView
+ style={styles.mainContainer}
+ contentContainerStyle={{paddingBottom: SCREEN_HEIGHT * 0.1}}>
<View style={styles.container}>
<Text style={styles.title}>{props.sectionTitle}</Text>
{props.sectionButtonTitle && (
@@ -35,13 +39,14 @@ const RecentSearches: React.FC<RecentSearchesProps> = (props) => {
previewType={props.sectionTitle}
screenType={props.screenType}
/>
- </View>
+ </ScrollView>
);
};
const styles = StyleSheet.create({
mainContainer: {
marginLeft: '3%',
+ padding: 20,
},
container: {
flexDirection: 'row',
diff --git a/src/components/search/SearchResultCell.tsx b/src/components/search/SearchResultCell.tsx
new file mode 100644
index 00000000..705fb5c9
--- /dev/null
+++ b/src/components/search/SearchResultCell.tsx
@@ -0,0 +1,187 @@
+import {useNavigation} from '@react-navigation/native';
+import React, {useEffect, useState} from 'react';
+import {Alert, Image, StyleSheet, Text, View} from 'react-native';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+import {useDispatch, useStore} from 'react-redux';
+import {ERROR_UNABLE_TO_VIEW_PROFILE} from '../../constants/strings';
+import {loadImageFromURL} from '../../services';
+import {RootState} from '../../store/rootReducer';
+import {ProfilePreviewType, ScreenType, UserType} from '../../types';
+import {normalize, SCREEN_WIDTH} from '../../utils';
+import {
+ addUserToRecentlyViewed,
+ checkIfUserIsBlocked,
+ defaultUserProfile,
+ fetchUserX,
+ userXInStore,
+} from '../../utils/users';
+
+interface SearchResults {
+ profileData: ProfilePreviewType;
+ loggedInUser: UserType;
+}
+
+const SearchResultsCell: React.FC<SearchResults> = ({
+ profileData: {
+ id,
+ name,
+ username,
+ first_name,
+ last_name,
+ thumbnail_url,
+ category,
+ },
+ loggedInUser,
+}) => {
+ const [avatar, setAvatar] = useState<string | undefined>(undefined);
+ useEffect(() => {
+ (async () => {
+ if (thumbnail_url !== undefined) {
+ try {
+ const response = await loadImageFromURL(thumbnail_url);
+ if (response) {
+ setAvatar(response);
+ }
+ } catch (error) {
+ console.log('Error while downloading ', error);
+ throw error;
+ }
+ }
+ })();
+ }, [thumbnail_url]);
+
+ const dispatch = useDispatch();
+ const state: RootState = useStore().getState();
+ const navigation = useNavigation();
+ const addToRecentlyStoredAndNavigateToProfile = async () => {
+ try {
+ //If the logged in user is blocked by the user being viewed, do not proceed.
+ const isUserBlocked = await checkIfUserIsBlocked(
+ id,
+ dispatch,
+ loggedInUser,
+ );
+ if (isUserBlocked) {
+ Alert.alert(ERROR_UNABLE_TO_VIEW_PROFILE);
+ return;
+ }
+
+ await addUserToRecentlyViewed({
+ id,
+ first_name,
+ last_name,
+ thumbnail_url,
+ username,
+ });
+
+ const userXId = loggedInUser.username === username ? undefined : id;
+
+ /**
+ * Dispatch an event to Fetch the user details only if we're navigating to
+ * a userX's profile.
+ * If the user is already present in store, do not fetch again.
+ * Finally, Navigate to profile of the user selected.
+ */
+ if (userXId && !userXInStore(state, ScreenType.Search, id)) {
+ await fetchUserX(
+ dispatch,
+ {userId: id, username: username},
+ ScreenType.Search,
+ );
+ }
+
+ navigation.navigate('Profile', {
+ userXId,
+ screenType: ScreenType.Search,
+ });
+ } catch (e) {
+ console.log(e);
+ }
+ };
+
+ const userCell = () => {
+ return (
+ <TouchableOpacity
+ onPress={addToRecentlyStoredAndNavigateToProfile}
+ style={styles.cellContainer}>
+ <Image
+ defaultSource={defaultUserProfile()}
+ source={{uri: avatar}}
+ style={styles.imageContainer}
+ />
+ <View style={[styles.initialTextContainer, styles.multiText]}>
+ <Text style={styles.initialTextStyle}>{`@${username}`}</Text>
+ <Text style={styles.secondaryTextStyle}>
+ {first_name + ' ' + last_name}
+ </Text>
+ </View>
+ </TouchableOpacity>
+ );
+ };
+
+ const searchIcon = () => {
+ return require('../../assets/images/search.png');
+ };
+
+ const universityIcon = () => {
+ return require('../../assets/images/bwbadges.png');
+ };
+
+ const categoryCell = () => {
+ return (
+ <TouchableOpacity style={styles.cellContainer}>
+ <View style={[styles.imageContainer, styles.categoryBackground]}>
+ <Image
+ resizeMode="contain"
+ source={category === 'Brown' ? universityIcon() : searchIcon()}
+ style={styles.categoryImage}
+ />
+ </View>
+ <View style={styles.initialTextContainer}>
+ <Text style={styles.initialTextStyle}>{name}</Text>
+ </View>
+ </TouchableOpacity>
+ );
+ };
+
+ return name === undefined ? userCell() : categoryCell();
+};
+
+const styles = StyleSheet.create({
+ cellContainer: {
+ flexDirection: 'row',
+ marginHorizontal: SCREEN_WIDTH * 0.08,
+ marginBottom: SCREEN_WIDTH * 0.08,
+ },
+ imageContainer: {
+ width: SCREEN_WIDTH * 0.112,
+ height: SCREEN_WIDTH * 0.112,
+ borderRadius: (SCREEN_WIDTH * 0.112) / 2,
+ },
+ categoryBackground: {
+ backgroundColor: 'rgba(196, 196, 196, 0.45)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ categoryImage: {
+ width: '40%',
+ height: '40%',
+ },
+ initialTextContainer: {
+ marginLeft: SCREEN_WIDTH * 0.08,
+ flexDirection: 'column',
+ justifyContent: 'center',
+ },
+ initialTextStyle: {
+ fontWeight: '500',
+ fontSize: normalize(14),
+ },
+ secondaryTextStyle: {
+ fontWeight: '500',
+ fontSize: normalize(12),
+ color: '#828282',
+ },
+ multiText: {justifyContent: 'space-between'},
+});
+
+export default SearchResultsCell;
diff --git a/src/components/search/SearchResultList.tsx b/src/components/search/SearchResultList.tsx
new file mode 100644
index 00000000..a3d9c8c5
--- /dev/null
+++ b/src/components/search/SearchResultList.tsx
@@ -0,0 +1,93 @@
+import React, {useEffect, useState} from 'react';
+import {SectionList, StyleSheet, Text, View} from 'react-native';
+import {useSelector} from 'react-redux';
+import {RootState} from 'src/store/rootreducer';
+import {NO_RESULTS_FOUND} from '../../constants/strings';
+import {PreviewType, ScreenType} from '../../types';
+import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import SearchResultsCell from './SearchResultCell';
+
+interface SearchResultsProps {
+ results: Array<any> | undefined;
+ keyboardVisible: boolean;
+ previewType: PreviewType;
+ screenType: ScreenType;
+}
+
+const sectionHeader: React.FC<Boolean> = (showBorder: Boolean) => {
+ if (showBorder) {
+ return <View style={styles.sectionHeaderStyle} />;
+ }
+ return null;
+};
+
+const SearchResultList: React.FC<SearchResultsProps> = ({
+ results,
+ keyboardVisible,
+}) => {
+ const [showSection, setShowSection] = useState(true);
+ const [showEmptyView, setshowEmptyView] = useState(false);
+ const {user: loggedInUser} = useSelector((state: RootState) => state.user);
+
+ useEffect(() => {
+ if (results && results.length > 0) {
+ setshowEmptyView(
+ results[0].data.length === 0 && results[1].data.length === 0,
+ );
+ }
+ }, [results]);
+
+ return (
+ <View style={styles.container}>
+ {showEmptyView && (
+ <View style={styles.noResultsTextContainer}>
+ <Text style={styles.noResultsTextStyle}>{NO_RESULTS_FOUND}</Text>
+ </View>
+ )}
+ {!showEmptyView && (
+ <SectionList
+ style={[
+ {width: SCREEN_WIDTH},
+ keyboardVisible ? styles.keyboardOpen : {},
+ ]}
+ contentContainerStyle={{paddingBottom: SCREEN_HEIGHT * 0.1}}
+ sections={results}
+ keyExtractor={(item, index) => item.id + index}
+ renderItem={({item}) => (
+ <SearchResultsCell profileData={item} loggedInUser={loggedInUser} />
+ )}
+ renderSectionHeader={({section: {title, data}}) => {
+ if (title === 'categories' && data.length === 0) {
+ setShowSection(false);
+ }
+ return sectionHeader(title !== 'categories' && showSection);
+ }}
+ />
+ )}
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ marginTop: SCREEN_HEIGHT * 0.02,
+ },
+ sectionHeaderStyle: {
+ width: '100%',
+ height: 0.5,
+ marginBottom: normalize(24),
+ backgroundColor: '#C4C4C4',
+ },
+ keyboardOpen: {marginBottom: SCREEN_HEIGHT * 0.3},
+ noResultsTextContainer: {
+ justifyContent: 'center',
+ flexDirection: 'row',
+ width: SCREEN_WIDTH,
+ },
+ noResultsTextStyle: {
+ fontWeight: '500',
+ fontSize: normalize(14),
+ },
+});
+
+export default SearchResultList;
diff --git a/src/components/search/SearchResultsBackground.tsx b/src/components/search/SearchResultsBackground.tsx
index 77b1821d..c5fcc6fb 100644
--- a/src/components/search/SearchResultsBackground.tsx
+++ b/src/components/search/SearchResultsBackground.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import Animated, {interpolate} from 'react-native-reanimated';
import {StyleSheet} from 'react-native';
+import Animated, {interpolate} from 'react-native-reanimated';
import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
interface SearchResultsBackgroundProps {
@@ -21,11 +21,9 @@ const SearchResultsBackground: React.FC<SearchResultsBackgroundProps> = ({
return (
<Animated.View
style={[styles.container, {opacity: opacityBackground, top}]}>
- <Animated.ScrollView
- contentContainerStyle={styles.contentContainer}
- style={[styles.results, {opacity: opacityContent}]}>
+ <Animated.View style={[styles.results, {opacity: opacityContent}]}>
{children}
- </Animated.ScrollView>
+ </Animated.View>
</Animated.View>
);
};
@@ -34,7 +32,6 @@ const styles = StyleSheet.create({
flex: 1,
height: SCREEN_HEIGHT,
width: SCREEN_WIDTH,
- padding: 20,
position: 'absolute',
backgroundColor: '#fff',
zIndex: 0,
diff --git a/src/components/search/index.ts b/src/components/search/index.ts
index 08052f77..7418f0ba 100644
--- a/src/components/search/index.ts
+++ b/src/components/search/index.ts
@@ -3,5 +3,6 @@ export {default as SearchHeader} from './SearchHeader';
export {default as SearchBar} from './SearchBar';
export {default as Explore} from './Explore';
export {default as SearchResultsBackground} from './SearchResultsBackground';
+export {default as SearchResultList} from './SearchResultList';
export {default as SearchResults} from './SearchResults';
export {default as DiscoverUsers} from './DiscoverUsers';
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 380dd061..07fa2b59 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -17,7 +17,7 @@ export const PROFILE_PHOTO_THUMBNAIL_ENDPOINT: string =
export const GET_IG_POSTS_ENDPOINT: string = API_URL + 'posts-ig/';
export const GET_FB_POSTS_ENDPOINT: string = API_URL + 'posts-fb/';
export const GET_TWITTER_POSTS_ENDPOINT: string = API_URL + 'posts-twitter/';
-export const SEARCH_ENDPOINT: string = API_URL + 'search/';
+export const SEARCH_ENDPOINT: string = API_URL + 'search/v2/';
export const MOMENTS_ENDPOINT: string = API_URL + 'moments/';
export const MOMENT_THUMBNAIL_ENDPOINT: string = API_URL + 'moment-thumbnail/';
export const VERIFY_INVITATION_CODE_ENDPOUNT: string = API_URL + 'verify-code/';
diff --git a/src/constants/strings.ts b/src/constants/strings.ts
index 104cc198..7652fccd 100644
--- a/src/constants/strings.ts
+++ b/src/constants/strings.ts
@@ -49,6 +49,7 @@ export const ERROR_VERIFICATION_FAILED_SHORT = 'Verification failed 😓';
export const MARKED_AS_MSG = (str: string) => `Marked as ${str}`;
export const MOMENT_DELETED_MSG = 'Moment deleted....Some moments have to go, to create space for greater ones';
export const NO_NEW_NOTIFICATIONS = 'You have no new notifications';
+export const NO_RESULTS_FOUND = 'No Results Found!';
export const SUCCESS_CATEGORY_DELETE = 'Category successfully deleted, but its memory will live on';
export const SUCCESS_LINK = (str: string) => `Successfully linked ${str} 🎉`;
export const SUCCESS_PIC_UPLOAD = 'Beautiful, the picture was uploaded successfully!';
diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx
index 84efa931..70733d7e 100644
--- a/src/screens/search/SearchScreen.tsx
+++ b/src/screens/search/SearchScreen.tsx
@@ -16,19 +16,16 @@ import {
SearchBackground,
SearchBar,
SearchHeader,
- SearchResults,
+ SearchResultList,
SearchResultsBackground,
TabsGradient,
} from '../../components';
import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants';
+import {loadSearchResults} from '../../services';
import {loadRecentlySearched, resetScreenType} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
-import {ProfilePreviewType, ScreenType, UserType} from '../../types';
+import {ProfilePreviewType, ScreenType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
-const NO_USER: UserType = {
- userId: '',
- username: '',
-};
/**
* Search Screen for user recommendations and a search
@@ -38,14 +35,27 @@ const NO_USER: UserType = {
const SearchScreen: React.FC = () => {
const {recentSearches} = useSelector((state: RootState) => state.taggUsers);
const [query, setQuery] = useState<string>('');
- const [results, setResults] = useState<Array<ProfilePreviewType>>([]);
+ const [results, setResults] = useState<Array<any> | undefined>(undefined);
const [recents, setRecents] = useState<Array<ProfilePreviewType>>(
recentSearches ?? [],
);
const [searching, setSearching] = useState(false);
const top = Animated.useValue(-SCREEN_HEIGHT);
const [refreshing, setRefreshing] = useState<boolean>(false);
+ const [keyboardVisible, setKeyboardVisible] = React.useState(
+ 'keyboardVisible',
+ );
+ useEffect(() => {
+ const showKeyboard = () => setKeyboardVisible('keyboardVisibleTrue');
+ Keyboard.addListener('keyboardWillShow', showKeyboard);
+ return () => Keyboard.removeListener('keyboardWillShow', showKeyboard);
+ }, []);
+ useEffect(() => {
+ const hideKeyboard = () => setKeyboardVisible('keyboardVisibleFalse');
+ Keyboard.addListener('keyboardWillHide', hideKeyboard);
+ return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard);
+ }, []);
const dispatch = useDispatch();
const onRefresh = useCallback(() => {
@@ -60,31 +70,31 @@ const SearchScreen: React.FC = () => {
useEffect(() => {
if (query.length < 3) {
- setResults([]);
+ setResults(undefined);
return;
}
- const loadResults = async (q: string) => {
- try {
- const token = await AsyncStorage.getItem('token');
- const response = await fetch(`${SEARCH_ENDPOINT}?query=${q}`, {
- method: 'GET',
- headers: {
- Authorization: 'Token ' + token,
+ (async () => {
+ const searchResults = await loadSearchResults(
+ `${SEARCH_ENDPOINT}?query=${query}`,
+ );
+ if (query.length > 2) {
+ const categories = searchResults?.categories;
+ const users = searchResults?.users;
+ const sanitizedResult = [
+ {
+ title: 'categories',
+ data: categories,
+ },
+ {
+ title: 'users',
+ data: users,
},
- });
- const status = response.status;
- if (status === 200) {
- let searchResults = await response.json();
- setResults(searchResults);
- return;
- }
- setResults([]);
- } catch (error) {
- console.log(error);
- setResults([]);
+ ];
+ setResults(sanitizedResult);
+ } else {
+ setResults(undefined);
}
- };
- loadResults(query);
+ })();
}, [query]);
/**
@@ -160,8 +170,9 @@ const SearchScreen: React.FC = () => {
{...{top, searching}}
/>
<Explore />
+
<SearchResultsBackground {...{top}}>
- {results.length === 0 && recents.length !== 0 ? (
+ {results === undefined && recents.length !== 0 ? (
<RecentSearches
sectionTitle="Recent"
sectionButtonTitle="Clear all"
@@ -170,8 +181,9 @@ const SearchScreen: React.FC = () => {
screenType={ScreenType.Search}
/>
) : (
- <SearchResults
+ <SearchResultList
{...{results}}
+ keyboardVisible={keyboardVisible === 'keyboardVisibleTrue'}
previewType={'Search'}
screenType={ScreenType.Search}
/>
diff --git a/src/screens/search/mock.ts b/src/screens/search/mock.ts
new file mode 100644
index 00000000..d9909b22
--- /dev/null
+++ b/src/screens/search/mock.ts
@@ -0,0 +1,118 @@
+const MockResults = () => {
+ return {
+ categories: [
+ {
+ id: 11,
+ name: "Brown '21",
+ category: 'Brown',
+ },
+ {
+ id: 12,
+ name: "Brown '22",
+ category: 'Brown',
+ },
+ {
+ id: 13,
+ name: "Brown '23",
+ category: null,
+ },
+ {
+ id: 14,
+ name: "Brown '24",
+ category: null,
+ },
+ ],
+ users: [
+ {
+ id: 'd5295557-59ce-49fc-aa8a-442874dbffc3',
+ username: 'foobar',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-d5295557-59ce-49fc-aa8a-442874dbffc3-thumbnail.jpg',
+ },
+ {
+ id: '31e93eb5-ccc9-4743-b053-eff368e23fa8',
+ username: 'foobar2',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-31e93eb5-ccc9-4743-b053-eff368e23fa8-thumbnail.jpg',
+ },
+ {
+ id: 'b1b68df9-97ac-48de-b00d-eab10a6a644a',
+ username: 'foobar3',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-b1b68df9-97ac-48de-b00d-eab10a6a644a-thumbnail.jpg',
+ },
+ {
+ id: 'b89c88b3-6b2f-4b6c-85d9-a03ff5396113',
+ username: 'foobar4',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-b89c88b3-6b2f-4b6c-85d9-a03ff5396113-thumbnail.jpg',
+ },
+ {
+ id: '73b4496a-0aa8-4115-98da-2070bf326134',
+ username: 'foobar5',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-73b4496a-0aa8-4115-98da-2070bf326134-thumbnail.jpg',
+ },
+ {
+ id: '329763b8-931e-4d4d-8a07-003374d38497',
+ username: 'foobar6',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-329763b8-931e-4d4d-8a07-003374d38497-thumbnail.jpg',
+ },
+ {
+ id: '9e82fea2-cddc-41e1-be05-6873f58138ca',
+ username: 'foobar7',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-9e82fea2-cddc-41e1-be05-6873f58138ca-thumbnail.jpg',
+ },
+ {
+ id: '6e5b8892-4384-45a1-bc0a-8f2c9d614fbc',
+ username: 'foobar8',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-6e5b8892-4384-45a1-bc0a-8f2c9d614fbc-thumbnail.jpg',
+ },
+ {
+ id: 'c49b01c6-9151-4654-8fae-834adfa15727',
+ username: 'foobar9',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-c49b01c6-9151-4654-8fae-834adfa15727-thumbnail.jpg',
+ },
+ {
+ id: '5b394d5b-62e3-405e-8ecd-7433517ef688',
+ username: 'foobar10',
+ first_name: 'Foo',
+ last_name: 'Bar',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-5b394d5b-62e3-405e-8ecd-7433517ef688-thumbnail.jpg',
+ },
+ {
+ id: '698e38f0-24ed-404c-9f0c-6a24e43af576',
+ username: 'fooo',
+ first_name: 'wefwef',
+ last_name: 'wefwef',
+ thumbnail_url:
+ 'https://tagg-dev.s3.us-east-2.amazonaws.com/thumbnails/smallProfilePicture/spp-698e38f0-24ed-404c-9f0c-6a24e43af576-thumbnail.jpg',
+ },
+ ],
+ };
+};
+
+export default MockResults;
diff --git a/src/services/SearchService.ts b/src/services/SearchService.ts
new file mode 100644
index 00000000..7b97f9a7
--- /dev/null
+++ b/src/services/SearchService.ts
@@ -0,0 +1,22 @@
+import AsyncStorage from '@react-native-community/async-storage';
+
+export const loadSearchResults = async (url: string) => {
+ try {
+ const token = await AsyncStorage.getItem('token');
+ const response = await fetch(url, {
+ method: 'GET',
+ headers: {
+ Authorization: 'Token ' + token,
+ },
+ });
+ const {status} = response;
+ if (status === 200) {
+ const searchResults = await response.json();
+ return searchResults;
+ }
+ } catch (error) {
+ console.log(error);
+ throw error;
+ }
+ return {};
+};
diff --git a/src/services/index.ts b/src/services/index.ts
index ef71233a..28e03e0e 100644
--- a/src/services/index.ts
+++ b/src/services/index.ts
@@ -12,3 +12,4 @@ export * from './WaitlistUserService';
export * from './CommonService';
export * from './CommentService';
export * from './SuggestedPeopleService';
+export * from './SearchService';
diff --git a/src/utils/users.ts b/src/utils/users.ts
index ca917ae4..653c941e 100644
--- a/src/utils/users.ts
+++ b/src/utils/users.ts
@@ -159,3 +159,40 @@ export const checkIfUserIsBlocked = async (
}
return await isUserBlocked(userId, loggedInUser.userId, token);
};
+
+export const defaultUserProfile = () => {
+ const defaultImage = require('../assets/images/avatar-placeholder.png');
+ return defaultImage;
+};
+
+export const addUserToRecentlyViewed = async (user: ProfilePreviewType) => {
+ const jsonValue = await AsyncStorage.getItem('@recently_searched_users');
+ let recentlySearchedList = jsonValue != null ? JSON.parse(jsonValue) : null;
+ if (recentlySearchedList) {
+ if (recentlySearchedList.length > 0) {
+ if (
+ recentlySearchedList.some(
+ (saved_user: ProfilePreviewType) => saved_user.id === user.id,
+ )
+ ) {
+ console.log('User already in recently searched.');
+ } else {
+ if (recentlySearchedList.length >= 10) {
+ recentlySearchedList.pop();
+ }
+ recentlySearchedList.unshift(user);
+ }
+ }
+ } else {
+ recentlySearchedList = [user];
+ }
+ try {
+ let recentlySearchedListString = JSON.stringify(recentlySearchedList);
+ await AsyncStorage.setItem(
+ '@recently_searched_users',
+ recentlySearchedListString,
+ );
+ } catch (e) {
+ console.log(e);
+ }
+};