diff options
author | Ashm Walia <40498934+ashmgarv@users.noreply.github.com> | 2021-01-12 15:38:21 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-12 18:38:21 -0500 |
commit | d495bff07b50c47e842dc2c139922d56c87f5c9b (patch) | |
tree | c6f592fa72a6158981fef2feba1b3dca5ff6cc2a /src/components | |
parent | c758389ad2ebe98196d4618ec08dbf2b24d95bfa (diff) |
[TMA 491 Frontend] Revamp onboarding (#173)
* First commit, arrow excluded
* Done from my side
* Some small nitpicks
* exclude tsconfig
* Show profile screen after onboarding
* Update string
* Small fix
* small cosmetic
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/common/TaggPopup.tsx | 19 | ||||
-rw-r--r-- | src/components/common/TaggPrompt.tsx | 79 | ||||
-rw-r--r-- | src/components/common/index.ts | 1 | ||||
-rw-r--r-- | src/components/moments/Moment.tsx | 28 | ||||
-rw-r--r-- | src/components/profile/Content.tsx | 84 |
5 files changed, 188 insertions, 23 deletions
diff --git a/src/components/common/TaggPopup.tsx b/src/components/common/TaggPopup.tsx index db24adb8..86a472b1 100644 --- a/src/components/common/TaggPopup.tsx +++ b/src/components/common/TaggPopup.tsx @@ -31,7 +31,11 @@ const TaggPopup: React.FC<TaggPopupProps> = ({route, navigation}) => { const {messageHeader, messageBody, next} = route.params.popupProps; return ( - <View style={styles.container}> + <TouchableOpacity + style={styles.container} + onPressOut={() => { + navigation.goBack(); + }}> <View style={styles.popup}> <Image style={styles.icon} @@ -61,7 +65,7 @@ const TaggPopup: React.FC<TaggPopupProps> = ({route, navigation}) => { /> </View> )} - </View> + </TouchableOpacity> ); }; @@ -92,23 +96,23 @@ const styles = StyleSheet.create({ }, header: { color: '#fff', - fontSize: 16, + fontSize: SCREEN_WIDTH / 25, fontWeight: '600', textAlign: 'justify', marginBottom: '2%', - marginHorizontal: '2%', + marginLeft: '4%', }, subtext: { color: '#fff', - fontSize: 12, + fontSize: SCREEN_WIDTH / 30, fontWeight: '600', textAlign: 'justify', marginBottom: '15%', - marginHorizontal: '2%', + marginLeft: '3%', }, popup: { width: SCREEN_WIDTH * 0.8, - height: SCREEN_WIDTH * 0.2, + height: SCREEN_WIDTH * 0.24, backgroundColor: 'black', borderRadius: 8, flexDirection: 'row', @@ -116,6 +120,7 @@ const styles = StyleSheet.create({ flexWrap: 'wrap', position: 'absolute', bottom: SCREEN_HEIGHT * 0.7, + padding: SCREEN_WIDTH / 40, }, footer: { marginLeft: '50%', diff --git a/src/components/common/TaggPrompt.tsx b/src/components/common/TaggPrompt.tsx new file mode 100644 index 00000000..5cd3ac3f --- /dev/null +++ b/src/components/common/TaggPrompt.tsx @@ -0,0 +1,79 @@ +import * as React from 'react'; +import {Platform, Text, StyleSheet, TouchableOpacity} from 'react-native'; +import {Image, View} from 'react-native-animatable'; +import {SCREEN_HEIGHT} from '../../utils'; +import CloseIcon from '../../assets/ionicons/close-outline.svg'; + +type TaggPromptProps = { + messageHeader: string; + messageBody: string; + logoType: string; + onClose: () => void; +}; + +const TaggPrompt: React.FC<TaggPromptProps> = ({ + messageHeader, + messageBody, + logoType, + onClose, +}) => { + /** + * Generic prompt for Tagg + */ + + return ( + <View style={styles.container}> + <Image + style={styles.icon} + source={require('../../assets/icons/plus-logo.png')} + /> + <Text style={styles.header}>{messageHeader}</Text> + <Text style={styles.subtext}>{messageBody}</Text> + <TouchableOpacity + style={styles.closeButton} + onPress={() => { + onClose(); + }}> + <CloseIcon height={'50%'} width={'50%'} color="gray" /> + </TouchableOpacity> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'white', + height: SCREEN_HEIGHT / 4.5, + paddingTop: SCREEN_HEIGHT / 10, + paddingBottom: SCREEN_HEIGHT / 50, + }, + closeButton: { + position: 'relative', + height: '40%', + bottom: SCREEN_HEIGHT / 6, + aspectRatio: 1, + alignSelf: 'flex-end', + }, + icon: { + width: 40, + height: 40, + }, + header: { + color: 'black', + fontSize: 16, + fontWeight: '600', + textAlign: 'center', + marginTop: '2%', + }, + subtext: { + color: 'gray', + fontSize: 12, + fontWeight: '500', + textAlign: 'center', + marginTop: '2%', + }, +}); +export default TaggPrompt; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index d5d36297..9162ec70 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -18,3 +18,4 @@ export {default as BottomDrawer} from './BottomDrawer'; export {default as TaggLoadingTndicator} from './TaggLoadingIndicator'; export {default as GenericMoreInfoDrawer} from './GenericMoreInfoDrawer'; export {default as TaggPopUp} from './TaggPopup'; +export {default as TaggPrompt} from './TaggPrompt'; diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index be6f78a8..446bc07b 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -1,6 +1,13 @@ import {useNavigation} from '@react-navigation/native'; import React from 'react'; -import {Alert, StyleSheet, View} from 'react-native'; +import { + Alert, + StyleProp, + StyleSheet, + View, + ViewProps, + ViewStyle, +} from 'react-native'; import {Text} from 'react-native-animatable'; import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; @@ -20,6 +27,7 @@ interface MomentProps { screenType: ScreenType; handleMomentCategoryDelete: (_: string) => void; shouldAllowDeletion: boolean; + externalStyles?: Record<string, StyleProp<ViewStyle>>; } const Moment: React.FC<MomentProps> = ({ @@ -29,6 +37,7 @@ const Moment: React.FC<MomentProps> = ({ screenType, handleMomentCategoryDelete, shouldAllowDeletion, + externalStyles, }) => { const navigation = useNavigation(); @@ -63,9 +72,11 @@ const Moment: React.FC<MomentProps> = ({ }); }; return ( - <View style={styles.container}> - <View style={styles.header}> - <Text style={styles.titleText}>{title}</Text> + <View style={[styles.container, externalStyles?.container]}> + <View style={[styles.header, externalStyles?.header]}> + <Text style={[styles.titleText, externalStyles?.titleText]}> + {title} + </Text> {!userXId ? ( <> <PlusIcon @@ -90,7 +101,7 @@ const Moment: React.FC<MomentProps> = ({ <ScrollView horizontal showsHorizontalScrollIndicator={false} - style={styles.scrollContainer}> + style={[styles.scrollContainer, externalStyles?.scrollContainer]}> {images && images.map((imageObj: MomentType) => ( <MomentTile @@ -107,7 +118,7 @@ const Moment: React.FC<MomentProps> = ({ <View style={styles.defaultImage}> <BigPlusIcon width={24} height={24} /> <Text style={styles.defaultImageText}> - Add a moment of your {title.toLowerCase()}! + Add a moment of your {title?.toLowerCase()}! </Text> </View> </LinearGradient> @@ -126,12 +137,9 @@ const styles = StyleSheet.create({ }, header: { flex: 1, - paddingLeft: '3%', - padding: 5, - paddingTop: 20, + padding: '3%', backgroundColor: 'white', flexDirection: 'row', - justifyContent: 'space-between', alignItems: 'center', }, titleText: { diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index 5fa05588..227e6783 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -43,8 +43,9 @@ import { } from '../../store/initialStates'; import {Cover} from '.'; import {TouchableOpacity} from 'react-native-gesture-handler'; -import {useNavigation} from '@react-navigation/native'; +import {useFocusEffect, useNavigation} from '@react-navigation/native'; import GreyPlusLogo from '../../assets/icons/grey-plus-logo.svg'; +import {TaggPrompt} from '../common'; interface ContentProps { y: Animated.Value<number>; @@ -97,6 +98,14 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { const [shouldBounce, setShouldBounce] = useState<boolean>(true); const [refreshing, setRefreshing] = useState<boolean>(false); + //These two booleans are used to see if user closed the pormpt displayed to them + const [isStageTwoPromptClosed, setIsStageTwoPromptClosed] = useState<boolean>( + false, + ); + const [isStageThreePromptClosed, setIsStageThreePromptClosed] = useState< + boolean + >(false); + const onRefresh = useCallback(() => { const refrestState = async () => { if (!userXId) { @@ -134,6 +143,43 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { }, [createImagesMap]); /** + * Prompt user to perform an activity based on their profile completion stage + * To fire 2 seconds after the screen comes in focus + * 1 means STAGE_1: + * The user must upload a moment, so take them to a screen guiding them to post a moment + * 2 means STAGE_2: + * The user must create another category so show a prompt on top of the screen + * 3 means STAGE_3: + * The user must upload a moment to the second category, so show a prompt on top of the screen + * Else, profile is complete and no prompt needs to be shown + */ + useFocusEffect( + useCallback(() => { + const navigateToMomentUploadPrompt = () => { + switch (profile.profile_completion_stage) { + case 1: + if (momentCategories && momentCategories[0]) { + navigation.navigate('MomentUploadPrompt', { + screenType, + momentCategory: momentCategories[0], + }); + } + break; + case 2: + setIsStageTwoPromptClosed(false); + break; + case 3: + setIsStageThreePromptClosed(false); + break; + default: + break; + } + }; + setTimeout(navigateToMomentUploadPrompt, 2000); + }, [profile.profile_completion_stage, momentCategories]), + ); + + /** * This hook is called on load of profile and when you update the friends list. */ useEffect(() => { @@ -227,10 +273,8 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { onPress: () => { dispatch( updateMomentCategories( - momentCategories.filter( - (mc) => mc !== category, - loggedInUser.userId, - ), + momentCategories.filter((mc) => mc !== category), + false, ), ); dispatch(deleteUserMomentsForCategory(category)); @@ -296,6 +340,34 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { } has not posted any moments yet`}</Text> </View> )} + {!userXId && + profile.profile_completion_stage === 2 && + !isStageTwoPromptClosed && ( + <TaggPrompt + messageHeader="Create a new category" + messageBody={ + 'Post your first moment to continue building your digital identity!' + } + logoType="" + onClose={() => { + setIsStageTwoPromptClosed(true); + }} + /> + )} + {!userXId && + profile.profile_completion_stage === 3 && + !isStageThreePromptClosed && ( + <TaggPrompt + messageHeader="Continue to build your profile" + messageBody={ + 'Continue to personalize your own digital space in\nthis community by filling your profile with\ncategories and moments!' + } + logoType="" + onClose={() => { + setIsStageThreePromptClosed(true); + }} + /> + )} {momentCategories.map( (title, index) => (!userXId || imagesMap.get(title)) && ( @@ -310,7 +382,7 @@ const Content: React.FC<ContentProps> = ({y, userXId, screenType}) => { /> ), )} - {!userXId && ( + {!userXId && profile.profile_completion_stage !== 1 && ( <TouchableOpacity onPress={() => navigation.push('CategorySelection', { |