From 84d283b44f2b6cecb757edcd94e717a36c3ba3c3 Mon Sep 17 00:00:00 2001
From: Ashm Walia <40498934+ashmgarv@users.noreply.github.com>
Date: Sat, 24 Oct 2020 16:12:39 -0700
Subject: [TMA 301] Add follow/unfollow button to profile (#70)

* Follow Unfollow User

* Fixed an issue and moved api call to Content.tsx

* last

* Small changes
---
 src/components/profile/Content.tsx | 83 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 2 deletions(-)

(limited to 'src/components/profile/Content.tsx')

diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx
index 8f20cd8d..8a3c36ff 100644
--- a/src/components/profile/Content.tsx
+++ b/src/components/profile/Content.tsx
@@ -3,7 +3,7 @@ import React, {useCallback, useEffect, useState} from 'react';
 import {Alert, LayoutChangeEvent, StyleSheet, View} from 'react-native';
 import Animated from 'react-native-reanimated';
 import {AuthContext, ProfileContext} from '../../routes/';
-import {MomentType} from 'src/types';
+import {MomentType, ProfilePreviewType} from 'src/types';
 import {defaultMoments, MOMENTS_ENDPOINT} from '../../constants';
 import {SCREEN_HEIGHT} from '../../utils';
 import TaggsBar from '../taggs/TaggsBar';
@@ -11,6 +11,7 @@ import {Moment} from '../moments';
 import ProfileBody from './ProfileBody';
 import ProfileCutout from './ProfileCutout';
 import ProfileHeader from './ProfileHeader';
+import {loadFollowers, followOrUnfollowUser} from '../../services';
 
 interface ContentProps {
   y: Animated.Value<number>;
@@ -22,10 +23,23 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => {
   const {newMomentsAvailable, updateMoments, user} = isProfileView
     ? React.useContext(ProfileContext)
     : React.useContext(AuthContext);
+  const {logout} = React.useContext(AuthContext);
   const [imagesList, setImagesList] = useState<MomentType[]>([]);
   const [imagesMap, setImagesMap] = useState<Map<string, MomentType[]>>(
     new Map(),
   );
+
+  const [followed, setFollowed] = React.useState<boolean>(false);
+  const [followers, setFollowers] = React.useState<Array<ProfilePreviewType>>(
+    [],
+  );
+  const {user: loggedInUser} = React.useContext(AuthContext);
+
+  /**
+   * If own profile is being viewed then do not show the follow button.
+   */
+  const isOwnProfile = loggedInUser.username === user.username;
+
   const onLayout = (e: LayoutChangeEvent) => {
     const {height} = e.nativeEvent.layout;
     setProfileBodyHeight(height);
@@ -80,6 +94,63 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => {
     }
   }, [userId, createImagesMap, updateMoments, newMomentsAvailable]);
 
+  /**
+   * This hook is called just on the load of profile.
+   */
+  useEffect(() => {
+    const updateFollowedValue = async () => {
+      const token = await AsyncStorage.getItem('token');
+      if (!token) {
+        logout();
+        return;
+      }
+
+      const listFollowers: ProfilePreviewType[] = await loadFollowers(
+        userId,
+        token,
+      );
+
+      /**
+       * Check if the logged in user actually follows the user being viewed.
+       */
+      const isActuallyFollowed = listFollowers.some(
+        (follower) => follower.username === loggedInUser.username,
+      );
+
+      if (followed != isActuallyFollowed) {
+        setFollowed(isActuallyFollowed);
+      }
+      setFollowers(listFollowers);
+    };
+
+    /**
+     * Update the followed value if and only if a profile is being viewed and you are loading a profile afresh that is not your own profile.
+     */
+    if (isProfileView && !isOwnProfile) {
+      updateFollowedValue();
+    }
+  }, []);
+
+  /**
+   * Handles a click on the follow / unfollow button.
+   */
+  const handleFollowUnfollow = async () => {
+    const token = await AsyncStorage.getItem('token');
+    if (!token) {
+      logout();
+      return;
+    }
+    const isUpdatedSuccessful = await followOrUnfollowUser(
+      loggedInUser.userId,
+      userId,
+      token,
+      followed,
+    );
+    if (isUpdatedSuccessful) {
+      setFollowed(!followed);
+    }
+  };
+
   return (
     <Animated.ScrollView
       style={styles.container}
@@ -90,7 +161,15 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => {
       <ProfileCutout>
         <ProfileHeader {...{isProfileView}} />
       </ProfileCutout>
-      <ProfileBody {...{onLayout, isProfileView}} />
+      <ProfileBody
+        {...{
+          onLayout,
+          isProfileView,
+          isOwnProfile,
+          followed,
+          handleFollowUnfollow,
+        }}
+      />
       <TaggsBar {...{y, profileBodyHeight, isProfileView}} />
       <View style={styles.momentsContainer}>
         {defaultMoments.map((title, index) => (
-- 
cgit v1.2.3-70-g09d2

