aboutsummaryrefslogtreecommitdiff
path: root/src/components/profile/PublicProfile.tsx
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-03-29 15:01:52 -0400
committerGitHub <noreply@github.com>2021-03-29 15:01:52 -0400
commitad2ad5d232473d38426c2f0f8283ba015dadfd4c (patch)
treef375a074fa23ca70c304f93b5577ed830250394c /src/components/profile/PublicProfile.tsx
parent4de1ebd43437712e28a89bb624c5b12afad45cc6 (diff)
parentee80ddfb8a486fea31d845aba4e0b4847fe637e9 (diff)
Merge pull request #306 from TaggiD-Inc/tma-701-private-account-banner
[TMA 701] : Separated Private and Public Profiles
Diffstat (limited to 'src/components/profile/PublicProfile.tsx')
-rw-r--r--src/components/profile/PublicProfile.tsx280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/components/profile/PublicProfile.tsx b/src/components/profile/PublicProfile.tsx
new file mode 100644
index 00000000..9683d8f2
--- /dev/null
+++ b/src/components/profile/PublicProfile.tsx
@@ -0,0 +1,280 @@
+import {useFocusEffect, useNavigation} from '@react-navigation/native';
+import React, {useCallback, useEffect, useState} from 'react';
+import {Alert, StyleSheet, Text, View} from 'react-native';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+import {useDispatch, useSelector} from 'react-redux';
+import GreyPlusLogo from '../../assets/icons/grey-plus-logo.svg';
+import {TAGG_LIGHT_BLUE} from '../../constants';
+import {
+ UPLOAD_MOMENT_PROMPT_THREE_HEADER,
+ UPLOAD_MOMENT_PROMPT_THREE_MESSAGE,
+ UPLOAD_MOMENT_PROMPT_TWO_HEADER,
+ UPLOAD_MOMENT_PROMPT_TWO_MESSAGE,
+} from '../../constants/strings';
+import {
+ deleteUserMomentsForCategory,
+ updateMomentCategories,
+} from '../../store/actions';
+import {
+ EMPTY_MOMENTS_LIST,
+ NO_PROFILE,
+ NO_USER,
+} from '../../store/initialStates';
+import {RootState} from '../../store/rootreducer';
+import {
+ CategorySelectionScreenType,
+ ContentProps,
+ MomentType,
+} from '../../types';
+import {moveCategory, normalize, SCREEN_HEIGHT} from '../../utils';
+import {TaggPrompt} from '../common';
+import {Moment} from '../moments';
+
+const PublicProfile: React.FC<ContentProps> = ({userXId, screenType}) => {
+ const dispatch = useDispatch();
+
+ const {profile = NO_PROFILE} = useSelector((state: RootState) =>
+ userXId ? state.userX[screenType][userXId] : state.user,
+ );
+
+ const {moments = EMPTY_MOMENTS_LIST} = useSelector((state: RootState) =>
+ userXId ? state.userX[screenType][userXId] : state.moments,
+ );
+
+ const {momentCategories = []} = useSelector((state: RootState) =>
+ userXId ? state.userX[screenType][userXId] : state.momentCategories,
+ );
+
+ const {user: loggedInUser = NO_USER} = useSelector(
+ (state: RootState) => state.user,
+ );
+
+ const navigation = useNavigation();
+
+ /**
+ * States
+ */
+ const [imagesMap, setImagesMap] = useState<Map<string, MomentType[]>>(
+ new Map(),
+ );
+
+ const [isStageTwoPromptClosed, setIsStageTwoPromptClosed] = useState(false);
+ const [isStageOnePromptClosed, setIsStageOnePromptClosed] = useState(false);
+ const [isStageThreePromptClosed, setIsStageThreePromptClosed] = useState(
+ false,
+ );
+
+ const move = (direction: 'up' | 'down', title: string) => {
+ let categories = [...momentCategories];
+ categories = moveCategory(categories, title, direction === 'up');
+ dispatch(updateMomentCategories(categories, false));
+ };
+
+ /**
+ * 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] &&
+ !isStageOnePromptClosed
+ ) {
+ navigation.navigate('MomentUploadPrompt', {
+ screenType,
+ momentCategory: momentCategories[0],
+ });
+ setIsStageOnePromptClosed(true);
+ }
+ break;
+ case 2:
+ setIsStageTwoPromptClosed(false);
+ break;
+ case 3:
+ setIsStageThreePromptClosed(false);
+ break;
+ default:
+ break;
+ }
+ };
+ if (!userXId) {
+ setTimeout(navigateToMomentUploadPrompt, 2000);
+ }
+ }, [
+ userXId,
+ profile.profile_completion_stage,
+ momentCategories,
+ isStageOnePromptClosed,
+ navigation,
+ screenType,
+ ]),
+ );
+
+ /**
+ * Handle deletion of a category
+ * Confirm with user before deleting the category
+ * @param category category to be deleted
+ */
+ const handleCategoryDeletion = (category: string) => {
+ Alert.alert(
+ 'Category Deletion',
+ `Are you sure that you want to delete the category ${category} ?`,
+ [
+ {
+ text: 'Cancel',
+ style: 'cancel',
+ },
+ {
+ text: 'Yes',
+ onPress: () => {
+ dispatch(
+ updateMomentCategories(
+ momentCategories.filter((mc) => mc !== category),
+ false,
+ ),
+ );
+ dispatch(deleteUserMomentsForCategory(category));
+ },
+ },
+ ],
+ {cancelable: true},
+ );
+ };
+
+ const createImagesMap = useCallback(() => {
+ let map = new Map();
+ moments.forEach(function (imageObject) {
+ let moment_category = imageObject.moment_category;
+ if (map.has(moment_category)) {
+ map.get(moment_category).push(imageObject);
+ } else {
+ map.set(moment_category, [imageObject]);
+ }
+ });
+ setImagesMap(map);
+ }, [moments]);
+
+ useEffect(() => {
+ createImagesMap();
+ }, [createImagesMap]);
+
+ return (
+ <View style={styles.momentsContainer}>
+ {userXId && moments.length === 0 && (
+ <View style={styles.plusIconContainer}>
+ <GreyPlusLogo width={90} height={90} />
+ <Text style={styles.noMomentsText}>{`Looks like ${
+ profile.name.split(' ')[0]
+ } has not posted any moments yet`}</Text>
+ </View>
+ )}
+ {!userXId &&
+ profile.profile_completion_stage === 2 &&
+ !isStageTwoPromptClosed && (
+ <TaggPrompt
+ messageHeader={UPLOAD_MOMENT_PROMPT_TWO_HEADER}
+ messageBody={UPLOAD_MOMENT_PROMPT_TWO_MESSAGE}
+ logoType="tagg"
+ onClose={() => {
+ setIsStageTwoPromptClosed(true);
+ }}
+ />
+ )}
+ {!userXId &&
+ profile.profile_completion_stage === 3 &&
+ !isStageThreePromptClosed && (
+ <TaggPrompt
+ messageHeader={UPLOAD_MOMENT_PROMPT_THREE_HEADER}
+ messageBody={UPLOAD_MOMENT_PROMPT_THREE_MESSAGE}
+ logoType="tagg"
+ onClose={() => {
+ setIsStageThreePromptClosed(true);
+ }}
+ />
+ )}
+ {momentCategories.map(
+ (title, index) =>
+ (!userXId || imagesMap.get(title)) && (
+ <Moment
+ key={index}
+ title={title}
+ images={imagesMap.get(title)}
+ userXId={userXId}
+ screenType={screenType}
+ handleMomentCategoryDelete={handleCategoryDeletion}
+ shouldAllowDeletion={momentCategories.length > 1}
+ showUpButton={index !== 0}
+ showDownButton={index !== momentCategories.length - 1}
+ move={move}
+ />
+ ),
+ )}
+ {!userXId && (
+ <TouchableOpacity
+ onPress={() =>
+ navigation.navigate('CategorySelection', {
+ screenType: CategorySelectionScreenType.Profile,
+ user: loggedInUser,
+ })
+ }
+ style={styles.createCategoryButton}>
+ <Text style={styles.createCategoryButtonLabel}>
+ Create a new category
+ </Text>
+ </TouchableOpacity>
+ )}
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#fff',
+ },
+ momentsContainer: {
+ backgroundColor: '#f2f2f2',
+ paddingBottom: SCREEN_HEIGHT * 0.15,
+ flex: 1,
+ flexDirection: 'column',
+ },
+ createCategoryButton: {
+ backgroundColor: TAGG_LIGHT_BLUE,
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: '70%',
+ height: 30,
+ marginTop: '15%',
+ alignSelf: 'center',
+ },
+ createCategoryButtonLabel: {
+ fontSize: normalize(16),
+ fontWeight: '500',
+ color: 'white',
+ },
+ plusIconContainer: {
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginVertical: '10%',
+ },
+ noMomentsText: {
+ fontSize: normalize(14),
+ fontWeight: 'bold',
+ color: 'gray',
+ marginVertical: '8%',
+ },
+});
+
+export default PublicProfile;