From eed77b91d4d10dece7c53a81eb92b8ac94cc1f77 Mon Sep 17 00:00:00 2001 From: ankit-thanekar007 Date: Thu, 25 Feb 2021 17:43:13 -0800 Subject: Request-Contacts updated permission request code --- src/constants/strings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/constants') diff --git a/src/constants/strings.ts b/src/constants/strings.ts index 5ae19e9c..353e0d02 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -25,7 +25,7 @@ export const ERROR_INVALID_VERIFICATION_CODE_FORMAT = 'Please enter the 6 digit export const ERROR_INVLAID_CODE = 'The code entered is not valid!'; export const ERROR_LINK = (str: string) => `Unable to link with ${str}, Please check your login and try again`; export const ERROR_LOGIN = 'There was a problem logging you in, please refresh and try again'; -export const ERROR_LOGIN_FAILED = 'Login failed. Check your username and passoword, and try again'; +export const ERROR_LOGIN_FAILED = 'Login failed. Check your username and password, and try again'; export const ERROR_NEXT_PAGE = 'There was a problem while loading the next page πŸ˜“, try again in a couple minutes'; export const ERROR_PROFILE_CREATION_SHORT = 'Profile creation failed πŸ˜“'; export const ERROR_PWD_ACCOUNT = (str: string) => `Please make sure that the email / username entered is registered with us. You may contact our customer support at ${str}`; -- cgit v1.2.3-70-g09d2 From bd3e189405e013b847b74fbad66543f6368a4ec8 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 26 Feb 2021 21:14:16 -0500 Subject: strings constant and remove/comment out old onboarding screens --- src/constants/strings.ts | 6 ++ src/routes/onboarding/OnboardingStackNavigator.tsx | 63 +++++++------- src/routes/onboarding/OnboardingStackScreen.tsx | 95 ++++++++-------------- 3 files changed, 69 insertions(+), 95 deletions(-) (limited to 'src/constants') diff --git a/src/constants/strings.ts b/src/constants/strings.ts index 353e0d02..104cc198 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -14,6 +14,7 @@ export const ERROR_DELETED_OBJECT = 'Oh sad! Looks like the comment / moment was export const ERROR_DOUBLE_CHECK_CONNECTION = 'Please double-check your network connection and retry'; export const ERROR_DUP_OLD_PWD = 'You may not use a previously used password'; export const ERROR_EMAIL_IN_USE = 'Email already in use, please try another one'; +export const ERROR_PHONE_IN_USE = 'Phone already in use, please try another one'; export const ERROR_FAILED_LOGIN_INFO = 'Login failed, please try re-entering your login information'; export const ERROR_FAILED_TO_COMMENT = 'Unable to post comment, refresh and try again!'; export const ERROR_FAILED_TO_DELETE_COMMENT = 'Unable to delete comment, refresh and try again!'; @@ -31,7 +32,10 @@ export const ERROR_PROFILE_CREATION_SHORT = 'Profile creation failed πŸ˜“'; export const ERROR_PWD_ACCOUNT = (str: string) => `Please make sure that the email / username entered is registered with us. You may contact our customer support at ${str}`; export const ERROR_REGISTRATION = (str: string) => `Registration failed πŸ˜”, ${str}`; export const ERROR_SELECT_CLASS_YEAR = 'Please select your Class Year'; +export const ERROR_SELECT_BIRTHDAY = 'Please select your birthday'; +export const ERROR_SELECT_GENDER = 'Please select your gender'; export const ERROR_SERVER_DOWN = 'mhm, looks like our servers are down, please refresh and try again in a few mins'; +export const ERROR_TWILIO_SERVER_ERROR = 'mhm, looks like that is an invalid phone number or our servers are down, please try again in a few mins'; export const ERROR_SOMETHING_WENT_WRONG = 'Oh dear, don’t worry someone will be held responsible for this error, In the meantime refresh the app'; export const ERROR_SOMETHING_WENT_WRONG_REFRESH = "Ha, looks like this one's on us, please refresh and try again"; export const ERROR_SOMETHING_WENT_WRONG_RELOAD = "You broke it, Just kidding! we don't know what happened... Please reload the app and try again"; @@ -50,6 +54,8 @@ export const SUCCESS_LINK = (str: string) => `Successfully linked ${str} πŸŽ‰`; export const SUCCESS_PIC_UPLOAD = 'Beautiful, the picture was uploaded successfully!'; export const SUCCESS_PWD_RESET = 'Your password was reset successfully!'; export const SUCCESS_VERIFICATION_CODE_SENT = 'New verification code sent! Check your phone messages for your code'; +export const SUCCESS_INVITATION_CODE = 'Perfect! You entered a valid invitation code, you are now able to login and explore Tagg!'; +export const ERROR_NOT_ONBOARDED = 'You are now on waitlist, please enter your invitation code if you have one'; export const UP_TO_DATE = 'Up-to-Date!'; export const UPLOAD_MOMENT_PROMPT_ONE_MESSAGE = 'Post your first moment to\n continue building your digital\nidentity!'; export const UPLOAD_MOMENT_PROMPT_THREE_HEADER = 'Continue to build your profile'; diff --git a/src/routes/onboarding/OnboardingStackNavigator.tsx b/src/routes/onboarding/OnboardingStackNavigator.tsx index 9f614f7c..0cdeecdf 100644 --- a/src/routes/onboarding/OnboardingStackNavigator.tsx +++ b/src/routes/onboarding/OnboardingStackNavigator.tsx @@ -1,46 +1,41 @@ import {createStackNavigator} from '@react-navigation/stack'; -import { - CategorySelectionScreenType, - TaggPopupType, - UserType, - VerificationScreenType, -} from '../../types'; +import {TaggPopupType, VerificationScreenType} from '../../types'; export type OnboardingStackParams = { - WelcomeScreen: undefined; Login: undefined; + WelcomeScreen: undefined; PasswordResetRequest: undefined; - PasswordReset: { - value: string; - }; - InvitationCodeVerification: undefined; - RegistrationOne: undefined; - RegistrationTwo: {phone: string}; - RegistrationThree: { - firstName: string; - lastName: string; - phone: string; - email: string; - }; - Checkpoint: {username: string; userId: string}; + PasswordReset: {value: string}; Verification: {id: string; screenType: VerificationScreenType}; - ProfileOnboarding: {username: string; userId: string}; - SocialMedia: {username: string; userId: string}; - CategorySelection: { - screenType: CategorySelectionScreenType; - user: UserType; - newCustomCategory: string | undefined; - }; - CreateCustomCategory: { - screenType: CategorySelectionScreenType; - user: UserType; - existingCategories: string[]; - }; + // RegistrationOne: undefined; + // RegistrationTwo: {phone: string}; + // RegistrationThree: { + // firstName: string; + // lastName: string; + // phone: string; + // email: string; + // }; + // Checkpoint: {username: string; userId: string}; + // ProfileOnboarding: {username: string; userId: string}; + // SocialMedia: {username: string; userId: string}; + // CategorySelection: { + // screenType: CategorySelectionScreenType; + // user: UserType; + // newCustomCategory: string | undefined; + // }; + // CreateCustomCategory: { + // screenType: CategorySelectionScreenType; + // user: UserType; + // existingCategories: string[]; + // }; TaggPopup: { popupProps: TaggPopupType; }; - AddWaitlistUser: undefined; - WaitlistSuccess: undefined; + OnboardingStepOne: undefined; + PhoneVerification: {firstName: string; lastName: string; phone: string}; + OnboardingStepTwo: {firstName: string; lastName: string; phone: string}; + OnboardingStepThree: {userId: string; username: string}; + InvitationCodeVerification: {userId: string}; }; export const OnboardingStack = createStackNavigator(); diff --git a/src/routes/onboarding/OnboardingStackScreen.tsx b/src/routes/onboarding/OnboardingStackScreen.tsx index 78f113cc..79171efd 100644 --- a/src/routes/onboarding/OnboardingStackScreen.tsx +++ b/src/routes/onboarding/OnboardingStackScreen.tsx @@ -1,24 +1,20 @@ +import {StackCardInterpolationProps} from '@react-navigation/stack'; import React from 'react'; -import {OnboardingStack} from './OnboardingStackNavigator'; +import TaggPopup from '../../components/common/TaggPopup'; import { - Login, InvitationCodeVerification, - RegistrationOne, - RegistrationTwo, - RegistrationThree, - Verification, - ProfileOnboarding, - Checkpoint, - SocialMedia, - PasswordResetRequest, + Login, + OnboardingStepThree, + OnboardingStepTwo, PasswordReset, + PasswordResetRequest, + PhoneVerification, + Verification, WelcomeScreen, - CategorySelection, - AddWaitlistUserScreen, - WaitlistSuccessScreen, } from '../../screens'; -import {StackCardInterpolationProps} from '@react-navigation/stack'; -import TaggPopup from '../../components/common/TaggPopup'; +import OnboardingStepOne from '../../screens/onboarding/OnboardingStepOne'; +import {modalStyle} from '../main'; +import {OnboardingStack} from './OnboardingStackNavigator'; const forFade = ({current}: StackCardInterpolationProps) => ({ cardStyle: { @@ -37,6 +33,7 @@ const Onboarding: React.FC = () => { options={{ gestureEnabled: false, cardStyleInterpolator: forFade, + ...modalStyle, }} /> { gestureEnabled: false, }} /> - - + ({ - cardStyle: { - opacity: progress.interpolate({ - inputRange: [0, 0.5, 0.9, 1], - outputRange: [0, 0.25, 0.7, 1], - }), - }, - }), + ...modalStyle, }} /> { component={PasswordReset} options={{ gestureEnabled: false, + ...modalStyle, }} /> - - - - ); }; -- cgit v1.2.3-70-g09d2 From 6bfa20c4f7ac22c78b29e6b4c09fe055f58b1922 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Mon, 1 Mar 2021 13:43:26 -0500 Subject: added brown 24 --- src/constants/constants.ts | 6 ++++-- src/services/ExploreService.ts | 1 + src/store/initialStates.ts | 1 + src/types/types.ts | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/constants') diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 6e2c9e1c..14bff6a7 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -173,13 +173,15 @@ 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 '21", - "Brown '22", + "Brown '24", "Brown '23", + "Brown '22", + "Brown '21", ]; export const SP_WIDTH = 375; diff --git a/src/services/ExploreService.ts b/src/services/ExploreService.ts index 980258be..dc58bdd0 100644 --- a/src/services/ExploreService.ts +++ b/src/services/ExploreService.ts @@ -50,6 +50,7 @@ export const getAllExploreSections = async () => { "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; diff --git a/src/store/initialStates.ts b/src/store/initialStates.ts index 4b61a2b1..1a3db433 100644 --- a/src/store/initialStates.ts +++ b/src/store/initialStates.ts @@ -79,6 +79,7 @@ export const EMPTY_EXPLORE_SECTIONS: Record< "Brown '21": EMPTY_PROFILE_PREVIEW_LIST, "Brown '22": EMPTY_PROFILE_PREVIEW_LIST, "Brown '23": EMPTY_PROFILE_PREVIEW_LIST, + "Brown '24": EMPTY_PROFILE_PREVIEW_LIST, }; export const NO_TAGG_USERS = { diff --git a/src/types/types.ts b/src/types/types.ts index 3ad787f2..7cd11f7a 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -126,7 +126,8 @@ export type ExploreSectionType = | 'Trending on Tagg' | "Brown '21" | "Brown '22" - | "Brown '23"; + | "Brown '23" + | "Brown '24"; /** * Redux store to have a Record of ScreenType (Search, Profile, Home etc) mapped to -- cgit v1.2.3-70-g09d2 From f14a3582e6b8dc19573b48b035fe31c560dac77a Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Tue, 2 Mar 2021 16:25:49 -0500 Subject: renamed and changed logic to check for multiple versions --- src/constants/api.ts | 2 +- src/routes/Routes.tsx | 6 +++--- src/services/CommonService.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/constants') diff --git a/src/constants/api.ts b/src/constants/api.ts index 57c26824..380dd061 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -4,7 +4,7 @@ const BASE_URL: string = 'http://127.0.0.1:8000/'; // local server const API_URL: string = BASE_URL + 'api/'; export const LOGIN_ENDPOINT: string = API_URL + 'login/'; -export const VERSION_ENDPOINT: string = API_URL + 'version/'; +export const VERSION_ENDPOINT: string = API_URL + 'version/v2/'; 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/'; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index 1cbc9bc5..01ffacab 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -3,7 +3,7 @@ import React, {useEffect, useState} from 'react'; import DeviceInfo from 'react-native-device-info'; import SplashScreen from 'react-native-splash-screen'; import {useDispatch, useSelector} from 'react-redux'; -import {fcmService, getLiveVersion} from '../services'; +import {fcmService, getCurrentLiveVersions} from '../services'; import { updateNewNotificationReceived, updateNewVersionAvailable, @@ -54,8 +54,8 @@ const Routes: React.FC = () => { useEffect(() => { const checkVersion = async () => { - const liveVersion = await getLiveVersion(); - if (liveVersion && liveVersion !== DeviceInfo.getVersion()) { + const liveVersions = await getCurrentLiveVersions(); + if (liveVersions.includes(DeviceInfo.getVersion())) { setNewVersionAvailable(true); dispatch(updateNewVersionAvailable(true)); } diff --git a/src/services/CommonService.ts b/src/services/CommonService.ts index 9fa7417f..5bc1174d 100644 --- a/src/services/CommonService.ts +++ b/src/services/CommonService.ts @@ -22,7 +22,7 @@ export const loadImageFromURL = async (url: string) => { } }; -export const getLiveVersion = async () => { +export const getCurrentLiveVersions = async () => { try { const response = await fetch(VERSION_ENDPOINT, {method: 'GET'}); return response.status === 200 ? await response.json() : undefined; -- cgit v1.2.3-70-g09d2 From af349a745bb00b5260f84909320d511ae9d0af2b Mon Sep 17 00:00:00 2001 From: ankit-thanekar007 Date: Tue, 2 Mar 2021 17:28:02 -0800 Subject: updated formatting, minor changes and integration testing --- src/assets/images/bwbadges.png | Bin 0 -> 528 bytes src/assets/images/bwbadges@2x.png | Bin 0 -> 991 bytes src/assets/images/bwbadges@3x.png | Bin 0 -> 1438 bytes src/assets/images/search.png | Bin 0 -> 354 bytes src/assets/images/search@2x.png | Bin 0 -> 643 bytes src/assets/images/search@3x.png | Bin 0 -> 901 bytes src/components/search/SearchResultCell.tsx | 208 ++++++++++++++++------------- src/components/search/SearchResultList.tsx | 64 ++++----- src/constants/api.ts | 1 + src/screens/search/SearchScreen.tsx | 100 +++++++++----- src/screens/search/mock.ts | 4 + 11 files changed, 218 insertions(+), 159 deletions(-) create mode 100644 src/assets/images/bwbadges.png create mode 100644 src/assets/images/bwbadges@2x.png create mode 100644 src/assets/images/bwbadges@3x.png create mode 100644 src/assets/images/search.png create mode 100644 src/assets/images/search@2x.png create mode 100644 src/assets/images/search@3x.png (limited to 'src/constants') diff --git a/src/assets/images/bwbadges.png b/src/assets/images/bwbadges.png new file mode 100644 index 00000000..3a337775 Binary files /dev/null and b/src/assets/images/bwbadges.png differ diff --git a/src/assets/images/bwbadges@2x.png b/src/assets/images/bwbadges@2x.png new file mode 100644 index 00000000..60c2f995 Binary files /dev/null and b/src/assets/images/bwbadges@2x.png differ diff --git a/src/assets/images/bwbadges@3x.png b/src/assets/images/bwbadges@3x.png new file mode 100644 index 00000000..874c0c4d Binary files /dev/null and b/src/assets/images/bwbadges@3x.png differ diff --git a/src/assets/images/search.png b/src/assets/images/search.png new file mode 100644 index 00000000..ba9906ba Binary files /dev/null and b/src/assets/images/search.png differ diff --git a/src/assets/images/search@2x.png b/src/assets/images/search@2x.png new file mode 100644 index 00000000..fa133ae1 Binary files /dev/null and b/src/assets/images/search@2x.png differ diff --git a/src/assets/images/search@3x.png b/src/assets/images/search@3x.png new file mode 100644 index 00000000..3ea4ce15 Binary files /dev/null and b/src/assets/images/search@3x.png differ diff --git a/src/components/search/SearchResultCell.tsx b/src/components/search/SearchResultCell.tsx index 46d5ee44..cdeed922 100644 --- a/src/components/search/SearchResultCell.tsx +++ b/src/components/search/SearchResultCell.tsx @@ -1,100 +1,128 @@ -import React, {useEffect, useState} from 'react'; -import {ProfilePreviewType, PreviewType, ScreenType} from '../../types'; -import ProfilePreview from '../profile/ProfilePreview'; -import {Image, SectionList, StyleSheet, View, Text} from 'react-native'; -import {normalize} from '../../utils'; -import {defaultUserProfile} from '../../utils/users'; -import {loadImageFromURL} from '../../services'; +import React, { useEffect, useState } from 'react'; +import { Image, StyleSheet, Text, View } from 'react-native'; +import { loadImageFromURL } from '../../services'; +import { ProfilePreviewType } from '../../types'; +import { normalize, SCREEN_WIDTH } from '../../utils'; +import { defaultUserProfile } from '../../utils/users'; +interface SearchResults { + profileData: ProfilePreviewType; +} -const SearchResultsCell: React.FC = ({ - item: {id, name, username, first_name, last_name, thumbnail_url}, - }) => { - const [avatar, setAvatar] = useState(''); - useEffect(() => { - (async () => { - const response = await loadImageFromURL(thumbnail_url); - if (response) { - setAvatar(response); +const SearchResultsCell: React.FC = ({ + profileData: { + id, + name, + username, + first_name, + last_name, + thumbnail_url, + category, + }, +}) => { + const [avatar, setAvatar] = useState(''); + 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; } - })(); - }, []); - - const userCell = () => { - return ( - - - - - {username} - - - {first_name + ' ' + last_name} - - + } + })(); + }, [thumbnail_url]); + + const userCell = () => { + return ( + + + + {`@${username}`} + + {first_name + ' ' + last_name} + - ); - }; - - const categoryCell = () => { - return ( - + + ); + }; + + const searchIcon = () => { + return require('../../assets/images/search.png'); + }; + + const universityIcon = () => { + return require('../../assets/images/bwbadges.png'); + }; + + const categoryCell = () => { + return ( + + - - - {name} - - - ); - }; - - return ( - <> - {name !== undefined && categoryCell()} - {name === undefined && userCell()} - + + {name} + + ); }; - export default SearchResultsCell \ No newline at end of file + return ( + <> + {name !== undefined && categoryCell()} + {name === undefined && userCell()} + + ); +}; + +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 index 702ce7c8..c464e7b1 100644 --- a/src/components/search/SearchResultList.tsx +++ b/src/components/search/SearchResultList.tsx @@ -1,10 +1,11 @@ -import React, {useEffect, useState} from 'react'; -import {ProfilePreviewType, PreviewType, ScreenType} from '../../types'; -import ProfilePreview from '../profile/ProfilePreview'; -import {Image, SectionList, StyleSheet, View, Text} from 'react-native'; -import {normalize} from '../../utils'; -import {defaultUserProfile} from '../../utils/users'; -import {loadImageFromURL} from '../../services'; +import React from 'react'; +import { + SectionList, + StyleSheet, + View +} from 'react-native'; +import { PreviewType, ScreenType } from '../../types'; +import { normalize, SCREEN_HEIGHT } from '../../utils'; import SearchResultsCell from './SearchResultCell'; interface SearchResultsProps { @@ -13,37 +14,36 @@ interface SearchResultsProps { screenType: ScreenType; } +const sectionHeader: React.FC = (showBorder: Boolean) => { + if (showBorder) { + return ; + } + return null; +}; + const SearchResultList: React.FC = ({results}) => { return ( - - item + index} - renderItem={({item}) => } - renderSectionHeader={({section: {title}}) => { - if (title === 'categories') { - return ; - } - return ( - - ); - }} - /> - + item + index} + renderItem={({item}) => } + renderSectionHeader={({section: {title}}) => + sectionHeader(title !== 'categories') + } + /> ); }; const styles = StyleSheet.create({ - containerSearch: {flexDirection: 'column', flexWrap: 'wrap'}, - container: {flex: 1, marginTop: 24}, + container: {flex: 1, marginTop: SCREEN_HEIGHT * 0.02}, + sectionHeaderStyle: { + width: '100%', + height: 0.5, + marginBottom: normalize(24), + backgroundColor: '#C4C4C4', + }, }); export default SearchResultList; diff --git a/src/constants/api.ts b/src/constants/api.ts index 57c26824..5e23ac7e 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -18,6 +18,7 @@ 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_V2_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/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index c3bd9fec..39b0425d 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -21,7 +21,11 @@ import { SearchResultList, TabsGradient, } from '../../components'; -import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants'; +import { + SEARCH_ENDPOINT, + SEARCH_V2_ENDPOINT, + TAGG_LIGHT_BLUE, +} from '../../constants'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; @@ -40,7 +44,7 @@ const NO_USER: UserType = { const SearchScreen: React.FC = () => { const {recentSearches} = useSelector((state: RootState) => state.taggUsers); const [query, setQuery] = useState(''); - const [results, setResults] = useState([]); + const [results, setResults] = useState(Array()); const [recents, setRecents] = useState>( recentSearches ?? [], ); @@ -65,40 +69,62 @@ const SearchScreen: React.FC = () => { setResults([]); 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, - // }, - // }); - // const status = response.status; - // if (status === 200) { - // let searchResults = await response.json(); - // setResults(searchResults); - // return; - // } - // setResults([]); - // } catch (error) { - // console.log(error); - // setResults([]); - // } - const searchResults = MockResults(); - const sanitizedResult = [ - { - title: 'categories', - data: searchResults.categories, - }, - { - title: 'users', - data: searchResults.users, - }, - ]; - setResults(sanitizedResult); - }; - loadResults(query); + // const loadResults = async (q: string) => { + // try { + // const token = await AsyncStorage.getItem('token'); + // const response = await fetch(`${SEARCH_V2_ENDPOINT}?query=${q}`, { + // method: 'GET', + // headers: { + // Authorization: 'Token ' + token, + // }, + // }); + // const {status} = response; + // if (status === 200) { + // const searchResults = await response.json(); + // const sanitizedResult = [ + // { + // title: 'categories', + // data: searchResults.categories, + // }, + // { + // title: 'users', + // data: searchResults.users, + // }, + // ]; + // setResults(sanitizedResult); + // } else { + // const searchResults = MockResults(); + // const sanitizedResult = [ + // { + // title: 'categories', + // data: searchResults.categories, + // }, + // { + // title: 'users', + // data: searchResults.users, + // }, + // ]; + // setResults(sanitizedResult); + // } + // setResults([]); + // } catch (error) { + // console.log(error); + // setResults([]); + // } + // }; + const searchResults = MockResults(); + const sanitizedResult = [ + { + title: 'categories', + data: searchResults.categories, + }, + { + title: 'users', + data: searchResults.users, + }, + ]; + setResults(sanitizedResult); + // loadResults(query); }, [query]); /** @@ -175,7 +201,7 @@ const SearchScreen: React.FC = () => { /> - {results && Object.keys(results).length === 0 ? ( + {results && results.length === 0 ? ( { { 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: [ -- cgit v1.2.3-70-g09d2 From 79396f899fe25f611d790d918e8ae4275a61e43c Mon Sep 17 00:00:00 2001 From: ankit-thanekar007 Date: Thu, 4 Mar 2021 16:06:21 -0800 Subject: TMA-663-Changes for empty view --- src/components/profile/ProfilePreview.tsx | 35 +-------- src/components/search/RecentSearches.tsx | 1 - src/components/search/SearchResultCell.tsx | 87 ++++++++++++++++++---- src/components/search/SearchResultList.tsx | 82 +++++++++++++++------ src/constants/api.ts | 3 +- src/constants/strings.ts | 1 + src/screens/search/SearchScreen.tsx | 114 +++++++++++++++-------------- src/services/SearchService.ts | 22 ++++++ src/services/index.ts | 1 + src/utils/users.ts | 32 ++++++++ 10 files changed, 249 insertions(+), 129 deletions(-) create mode 100644 src/services/SearchService.ts (limited to 'src/constants') 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 = ({ 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/RecentSearches.tsx b/src/components/search/RecentSearches.tsx index 43a26514..3925d084 100644 --- a/src/components/search/RecentSearches.tsx +++ b/src/components/search/RecentSearches.tsx @@ -54,7 +54,6 @@ const styles = StyleSheet.create({ marginBottom: '5%', }, clear: { - fontSize: 18, fontWeight: 'bold', color: TAGG_LIGHT_BLUE, diff --git a/src/components/search/SearchResultCell.tsx b/src/components/search/SearchResultCell.tsx index 084c6afe..705fb5c9 100644 --- a/src/components/search/SearchResultCell.tsx +++ b/src/components/search/SearchResultCell.tsx @@ -1,12 +1,24 @@ +import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; -import {Image, StyleSheet, Text, View} from 'react-native'; +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 {ProfilePreviewType} from '../../types'; +import {RootState} from '../../store/rootReducer'; +import {ProfilePreviewType, ScreenType, UserType} from '../../types'; import {normalize, SCREEN_WIDTH} from '../../utils'; -import {defaultUserProfile} from '../../utils/users'; +import { + addUserToRecentlyViewed, + checkIfUserIsBlocked, + defaultUserProfile, + fetchUserX, + userXInStore, +} from '../../utils/users'; interface SearchResults { profileData: ProfilePreviewType; + loggedInUser: UserType; } const SearchResultsCell: React.FC = ({ @@ -19,8 +31,9 @@ const SearchResultsCell: React.FC = ({ thumbnail_url, category, }, + loggedInUser, }) => { - const [avatar, setAvatar] = useState(''); + const [avatar, setAvatar] = useState(undefined); useEffect(() => { (async () => { if (thumbnail_url !== undefined) { @@ -37,9 +50,60 @@ const SearchResultsCell: React.FC = ({ })(); }, [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 ( - + = ({ {first_name + ' ' + last_name} - + ); }; @@ -65,7 +129,7 @@ const SearchResultsCell: React.FC = ({ const categoryCell = () => { return ( - + = ({ {name} - + ); }; - return ( - <> - {name !== undefined && categoryCell()} - {name === undefined && userCell()} - - ); + return name === undefined ? userCell() : categoryCell(); }; const styles = StyleSheet.create({ diff --git a/src/components/search/SearchResultList.tsx b/src/components/search/SearchResultList.tsx index bf08e205..7f8073c4 100644 --- a/src/components/search/SearchResultList.tsx +++ b/src/components/search/SearchResultList.tsx @@ -1,16 +1,20 @@ -import React, { useState } from 'react'; +import React, {useEffect, useState} from 'react'; import { + Keyboard, KeyboardAvoidingView, SectionList, StyleSheet, - View + Text, + View, } from 'react-native'; -import { PreviewType, ScreenType } from '../../types'; -import { normalize, SCREEN_HEIGHT } from '../../utils'; +import {useSelector} from 'react-redux'; +import {RootState} from 'src/store/rootreducer'; +import {PreviewType, ScreenType} from '../../types'; +import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import SearchResultsCell from './SearchResultCell'; - +import {NO_RESULTS_FOUND} from '../../constants/strings'; interface SearchResultsProps { - results: []; + results: Array | undefined; previewType: PreviewType; screenType: ScreenType; } @@ -24,34 +28,66 @@ const sectionHeader: React.FC = (showBorder: Boolean) => { const SearchResultList: React.FC = ({results}) => { 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 ( - - item + index} - renderItem={({item}) => } - renderSectionHeader={({section: {title, data}}) => { - if (title === 'categories' && data.length === 0) { - setShowSection(false); - } - return sectionHeader(title !== 'categories' && showSection); - }} - /> - - + + {showEmptyView && ( + + {NO_RESULTS_FOUND} + + )} + {!showEmptyView && ( + item.id + index} + renderItem={({item}) => ( + + )} + renderSectionHeader={({section: {title, data}}) => { + if (title === 'categories' && data.length === 0) { + setShowSection(false); + } + return sectionHeader(title !== 'categories' && showSection); + }} + /> + )} + ); }; const styles = StyleSheet.create({ - container: {marginTop: SCREEN_HEIGHT * 0.02}, + container: { + marginTop: SCREEN_HEIGHT * 0.04, + }, sectionHeaderStyle: { width: '100%', height: 0.5, marginBottom: normalize(24), backgroundColor: '#C4C4C4', }, + keyboardOpen: {marginBottom: SCREEN_HEIGHT * 0.3}, + keyboardClose: {marginBottom: 20}, + noResultsTextContainer: { + justifyContent: 'center', + flexDirection: 'row', + width: SCREEN_WIDTH, + }, + noResultsTextStyle: { + fontWeight: '500', + fontSize: normalize(14), + }, }); export default SearchResultList; diff --git a/src/constants/api.ts b/src/constants/api.ts index 5e23ac7e..1463683f 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -17,8 +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_V2_ENDPOINT: string = API_URL + 'search/v2/'; +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 a66a2cbc..b6841480 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -3,10 +3,12 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useState} from 'react'; import { Keyboard, + KeyboardAvoidingView, RefreshControl, ScrollView, StatusBar, StyleSheet, + SafeAreaView, } from 'react-native'; import Animated, {Easing, timing} from 'react-native-reanimated'; import {useDispatch, useSelector} from 'react-redux'; @@ -20,11 +22,12 @@ import { SearchResultsBackground, TabsGradient, } from '../../components'; -import {SEARCH_V2_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants'; +import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; +import {loadSearchResults} from '../../services'; const NO_USER: UserType = { userId: '', username: '', @@ -38,14 +41,27 @@ const NO_USER: UserType = { const SearchScreen: React.FC = () => { const {recentSearches} = useSelector((state: RootState) => state.taggUsers); const [query, setQuery] = useState(''); - const [results, setResults] = useState(Array()); + const [results, setResults] = useState | undefined>(undefined); const [recents, setRecents] = useState>( recentSearches ?? [], ); const [searching, setSearching] = useState(false); const top = Animated.useValue(-SCREEN_HEIGHT); const [refreshing, setRefreshing] = useState(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,48 +76,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_V2_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, }, - }); - const {status} = response; - if (status === 200) { - const searchResults = await response.json(); - const sanitizedResult = [ - { - title: 'categories', - data: searchResults.categories, - }, - { - title: 'users', - data: searchResults.users, - }, - ]; - - if ( - searchResults.categories.length !== 0 || - searchResults.users.length !== 0 - ) { - if (query.length > 3) { - setResults(sanitizedResult); - return; - } - } - } - } catch (error) { - console.log(error); + { + title: 'users', + data: users, + }, + ]; + setResults(sanitizedResult); + } else { + setResults(undefined); } - setResults([]); - }; - loadResults(query); + })(); }, [query]); /** @@ -179,24 +178,27 @@ const SearchScreen: React.FC = () => { - {results && results.length === 0 ? ( - - ) : ( - - )} + + {results === undefined && recents.length !== 0 ? ( + + ) : ( + + )} + - ); 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 b8faf206..653c941e 100644 --- a/src/utils/users.ts +++ b/src/utils/users.ts @@ -164,3 +164,35 @@ 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); + } +}; -- cgit v1.2.3-70-g09d2