From 43e1c33edf6fca78e366403f167cc01ea075a226 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Fri, 7 May 2021 15:12:13 -0400
Subject: added like button

---
 src/components/common/LikeButton.tsx | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 src/components/common/LikeButton.tsx

(limited to 'src/components/common/LikeButton.tsx')

diff --git a/src/components/common/LikeButton.tsx b/src/components/common/LikeButton.tsx
new file mode 100644
index 00000000..28eff768
--- /dev/null
+++ b/src/components/common/LikeButton.tsx
@@ -0,0 +1,32 @@
+import React, {useState} from 'react';
+import {Image, ImageStyle, StyleSheet, TouchableOpacity} from 'react-native';
+import {normalize} from '../../utils';
+
+interface LikeButtonProps {
+  onPress: () => void;
+  style: ImageStyle;
+}
+const LikeButton: React.FC<LikeButtonProps> = ({onPress, style}) => {
+  const [filled, setFilled] = useState(false);
+  const uri = filled
+    ? require('../../assets/images/heart-filled.png')
+    : require('../../assets/images/heart-outlined.png');
+  return (
+    <TouchableOpacity
+      onPress={() => {
+        setFilled(!filled);
+        onPress();
+      }}>
+      <Image style={[styles.image, style]} source={uri} />
+    </TouchableOpacity>
+  );
+};
+
+const styles = StyleSheet.create({
+  image: {
+    width: normalize(18),
+    height: normalize(15),
+  },
+});
+
+export default LikeButton;
-- 
cgit v1.2.3-70-g09d2


From 4f37038df45ee1aea6d42933ffa79f70a0a426d2 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Mon, 10 May 2021 15:17:45 -0400
Subject: added basic type, added like/unlike handler

---
 src/components/comments/CommentTile.tsx | 16 +++++++++++++---
 src/components/common/LikeButton.tsx    |  9 +++++++--
 src/services/CommentService.ts          | 18 +++++++++++++++++-
 src/types/types.ts                      | 11 +++++++++++
 4 files changed, 48 insertions(+), 6 deletions(-)

(limited to 'src/components/common/LikeButton.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index cc847885..8074a015 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -11,7 +11,11 @@ import Trash from '../../assets/ionicons/trash-outline.svg';
 import {TAGG_LIGHT_BLUE} from '../../constants';
 import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings';
 import {CommentContext} from '../../screens/profile/MomentCommentsScreen';
-import {deleteComment, getCommentsCount} from '../../services';
+import {
+  deleteComment,
+  getCommentsCount,
+  handleLikeUnlikeComment,
+} from '../../services';
 import {RootState} from '../../store/rootReducer';
 import {
   CommentThreadType,
@@ -145,7 +149,11 @@ const CommentTile: React.FC<CommentTileProps> = ({
             previewType={'Comment'}
             screenType={screenType}
           />
-          <LikeButton onPress={() => {}} style={styles.likeButton} />
+          <LikeButton
+            filled={commentObject.user_reaction !== undefined}
+            onPress={() => handleLikeUnlikeComment(commentObject)}
+            style={styles.likeButton}
+          />
         </View>
         <TouchableOpacity style={styles.body} onPress={toggleAddComment}>
           {renderTextWithMentions({
@@ -162,7 +170,9 @@ const CommentTile: React.FC<CommentTileProps> = ({
             </View>
             <View style={styles.row}>
               <TouchableOpacity style={styles.row} onPress={() => {}}>
-                <Text style={[styles.date_time, styles.likeCount]}>999</Text>
+                <Text style={[styles.date_time, styles.likeCount]}>
+                  {commentObject.reaction_count}
+                </Text>
                 <Text style={styles.date_time}>Likes</Text>
               </TouchableOpacity>
               {/* Show replies text only if there are some replies present  */}
diff --git a/src/components/common/LikeButton.tsx b/src/components/common/LikeButton.tsx
index 28eff768..f817bd98 100644
--- a/src/components/common/LikeButton.tsx
+++ b/src/components/common/LikeButton.tsx
@@ -4,10 +4,15 @@ import {normalize} from '../../utils';
 
 interface LikeButtonProps {
   onPress: () => void;
+  filled: boolean;
   style: ImageStyle;
 }
-const LikeButton: React.FC<LikeButtonProps> = ({onPress, style}) => {
-  const [filled, setFilled] = useState(false);
+const LikeButton: React.FC<LikeButtonProps> = ({
+  onPress,
+  filled: initialFillState,
+  style,
+}) => {
+  const [filled, setFilled] = useState(initialFillState);
   const uri = filled
     ? require('../../assets/images/heart-filled.png')
     : require('../../assets/images/heart-outlined.png');
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
index 2faaa8db..6f054c72 100644
--- a/src/services/CommentService.ts
+++ b/src/services/CommentService.ts
@@ -2,7 +2,7 @@ import AsyncStorage from '@react-native-community/async-storage';
 import {Alert} from 'react-native';
 import {COMMENTS_ENDPOINT, COMMENT_THREAD_ENDPOINT} from '../constants';
 import {ERROR_FAILED_TO_COMMENT} from '../constants/strings';
-import {CommentType} from '../types';
+import {CommentBaseType, CommentType} from '../types';
 
 export const getComments = async (
   objectId: string,
@@ -116,3 +116,19 @@ export const deleteComment = async (id: string, isThread: boolean) => {
     return false;
   }
 };
+
+/**
+ * If `user_reaction` is undefined, we like the comment, if `user_reaction`
+ * is defined, we unlike the comment.
+ *
+ * @param comment the comment object
+ * @returns
+ */
+export const handleLikeUnlikeComment = async (comment: CommentBaseType) => {
+  try {
+    return undefined;
+  } catch (error) {
+    console.log('Unable to like/unlike a comment');
+    console.error(error);
+  }
+};
diff --git a/src/types/types.ts b/src/types/types.ts
index 00501d49..e922d307 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -122,6 +122,8 @@ export interface CommentBaseType {
   comment: string;
   date_created: string;
   commenter: ProfilePreviewType;
+  user_reaction: ReactionType | undefined;
+  reaction_count: number;
 }
 
 export interface CommentType extends CommentBaseType {
@@ -316,3 +318,12 @@ export type ChatContextType = {
   >;
   chatClient: StreamChat;
 };
+
+export enum ReactionOptionsType {
+  Like = 'LIKE',
+}
+
+export type ReactionType = {
+  id: string;
+  type: ReactionOptionsType;
+};
-- 
cgit v1.2.3-70-g09d2


From 58ab56d0b03491dd062d09e2ee96fe8f88e74bc9 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 11 May 2021 17:55:43 -0400
Subject: fixed issue, basic functionality working

---
 src/components/comments/CommentTile.tsx       |  7 ++++---
 src/components/common/LikeButton.tsx          | 12 +++++++-----
 src/constants/api.ts                          |  1 +
 src/screens/profile/CommentReactionScreen.tsx |  2 +-
 src/services/CommentService.ts                | 24 ++++++++++++++++++------
 5 files changed, 31 insertions(+), 15 deletions(-)

(limited to 'src/components/common/LikeButton.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index e38946af..1f1fafda 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -150,10 +150,11 @@ const CommentTile: React.FC<CommentTileProps> = ({
             screenType={screenType}
           />
           <LikeButton
-            filled={commentObject.user_reaction !== null}
+            initialLikeState={commentObject.user_reaction !== null}
             onPress={() => {
-              handleLikeUnlikeComment(commentObject);
-              setShouldUpdateParent(true);
+              handleLikeUnlikeComment(commentObject).then(() => {
+                setShouldUpdateParent(true);
+              });
             }}
             style={styles.likeButton}
           />
diff --git a/src/components/common/LikeButton.tsx b/src/components/common/LikeButton.tsx
index f817bd98..43b3ac37 100644
--- a/src/components/common/LikeButton.tsx
+++ b/src/components/common/LikeButton.tsx
@@ -4,23 +4,25 @@ import {normalize} from '../../utils';
 
 interface LikeButtonProps {
   onPress: () => void;
-  filled: boolean;
   style: ImageStyle;
+  initialLikeState: boolean;
 }
 const LikeButton: React.FC<LikeButtonProps> = ({
   onPress,
-  filled: initialFillState,
   style,
+  initialLikeState,
 }) => {
-  const [filled, setFilled] = useState(initialFillState);
+  const [filled, setFilled] = useState(initialLikeState);
   const uri = filled
     ? require('../../assets/images/heart-filled.png')
     : require('../../assets/images/heart-outlined.png');
   return (
     <TouchableOpacity
       onPress={() => {
-        setFilled(!filled);
-        onPress();
+        if (filled === initialLikeState) {
+          setFilled(!filled);
+          onPress();
+        }
       }}>
       <Image style={[styles.image, style]} source={uri} />
     </TouchableOpacity>
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 2d9a60db..6a924f1d 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -33,6 +33,7 @@ export const MOMENT_THUMBNAIL_ENDPOINT: string = API_URL + 'moment-thumbnail/';
 export const VERIFY_INVITATION_CODE_ENDPOUNT: string = API_URL + 'verify-code/';
 export const COMMENTS_ENDPOINT: string = API_URL + 'comments/';
 export const COMMENT_REACTIONS_ENDPOINT: string = API_URL + 'reaction-comment/';
+export const COMMENT_REACTIONS_REPLY_ENDPOINT: string = API_URL + 'reaction-reply/';
 export const FRIENDS_ENDPOINT: string = API_URL + 'friends/';
 export const ALL_USERS_ENDPOINT: string = API_URL + 'users/';
 export const REPORT_ISSUE_ENDPOINT: string = API_URL + 'report/';
diff --git a/src/screens/profile/CommentReactionScreen.tsx b/src/screens/profile/CommentReactionScreen.tsx
index 488497ee..0596a184 100644
--- a/src/screens/profile/CommentReactionScreen.tsx
+++ b/src/screens/profile/CommentReactionScreen.tsx
@@ -29,7 +29,7 @@ const CommentReactionScreen: React.FC<CommentReactionScreenProps> = ({
     const loadUsers = async () => {
       const response = await getUsersReactedToAComment(comment);
       if (response.length !== 0) {
-        setUsers(users);
+        setUsers(response);
       } else {
         Alert.alert(ERROR_SOMETHING_WENT_WRONG);
         navigation.goBack();
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
index e85b1991..b21c6dfd 100644
--- a/src/services/CommentService.ts
+++ b/src/services/CommentService.ts
@@ -3,11 +3,13 @@ import {Alert} from 'react-native';
 import {
   COMMENTS_ENDPOINT,
   COMMENT_REACTIONS_ENDPOINT,
+  COMMENT_REACTIONS_REPLY_ENDPOINT,
   COMMENT_THREAD_ENDPOINT,
 } from '../constants';
 import {ERROR_FAILED_TO_COMMENT} from '../constants/strings';
 import {
   CommentBaseType,
+  CommentThreadType,
   CommentType,
   ProfilePreviewType,
   ReactionOptionsType,
@@ -133,12 +135,18 @@ export const deleteComment = async (id: string, isThread: boolean) => {
  * @param comment the comment object that contains `user_reaction` (or not)
  * @returns
  */
-export const handleLikeUnlikeComment = async (comment: CommentBaseType) => {
+export const handleLikeUnlikeComment = async (
+  comment: CommentType | CommentThreadType,
+) => {
   try {
+    const isReply = 'parent_comment' in comment;
     const token = await AsyncStorage.getItem('token');
+    let url = isReply
+      ? COMMENT_REACTIONS_REPLY_ENDPOINT
+      : COMMENT_REACTIONS_ENDPOINT;
     if (comment.user_reaction !== null) {
       // unlike a comment
-      const url = COMMENT_REACTIONS_ENDPOINT + `${comment.user_reaction.id}/`;
+      url += `${comment.user_reaction.id}/`;
       const response = await fetch(url, {
         method: 'DELETE',
         headers: {
@@ -148,7 +156,6 @@ export const handleLikeUnlikeComment = async (comment: CommentBaseType) => {
       return response.status === 200;
     } else {
       // like a comment
-      const url = COMMENT_REACTIONS_ENDPOINT;
       const form = new FormData();
       form.append('comment_id', comment.comment_id);
       form.append('reaction_type', ReactionOptionsType.Like);
@@ -168,11 +175,16 @@ export const handleLikeUnlikeComment = async (comment: CommentBaseType) => {
   }
 };
 
-export const getUsersReactedToAComment = async (comment: CommentBaseType) => {
+export const getUsersReactedToAComment = async (
+  comment: CommentType | CommentThreadType,
+) => {
   try {
+    const isReply = 'parent_comment' in comment;
     const token = await AsyncStorage.getItem('token');
-    const url =
-      COMMENT_REACTIONS_ENDPOINT + `?comment_id=${comment.comment_id}`;
+    let url = isReply
+      ? COMMENT_REACTIONS_REPLY_ENDPOINT
+      : COMMENT_REACTIONS_ENDPOINT;
+    url += `?comment_id=${comment.comment_id}`;
     const response = await fetch(url, {
       method: 'GET',
       headers: {
-- 
cgit v1.2.3-70-g09d2


From 51f397132d227edf5e07d48d673ee167d2aa5937 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 11 May 2021 18:42:53 -0400
Subject: made things faster

---
 src/components/comments/CommentTile.tsx | 14 +++++++-------
 src/components/common/LikeButton.tsx    | 17 ++++++++---------
 src/services/CommentService.ts          |  3 ++-
 3 files changed, 17 insertions(+), 17 deletions(-)

(limited to 'src/components/common/LikeButton.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 1f1fafda..ee32f889 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -55,6 +55,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
   const [showReplies, setShowReplies] = useState<boolean>(false);
   const [showKeyboard, setShowKeyboard] = useState<boolean>(false);
   const [shouldUpdateChild, setShouldUpdateChild] = useState(true);
+  const [liked, setLiked] = useState(commentObject.user_reaction !== null);
   const swipeRef = useRef<Swipeable>(null);
   const {replyPosted} = useSelector((state: RootState) => state.user);
   const state: RootState = useStore().getState();
@@ -150,12 +151,9 @@ const CommentTile: React.FC<CommentTileProps> = ({
             screenType={screenType}
           />
           <LikeButton
-            initialLikeState={commentObject.user_reaction !== null}
-            onPress={() => {
-              handleLikeUnlikeComment(commentObject).then(() => {
-                setShouldUpdateParent(true);
-              });
-            }}
+            liked={liked}
+            setLiked={setLiked}
+            onPress={() => handleLikeUnlikeComment(commentObject, liked)}
             style={styles.likeButton}
           />
         </View>
@@ -183,7 +181,9 @@ const CommentTile: React.FC<CommentTileProps> = ({
                   });
                 }}>
                 <Text style={[styles.date_time, styles.likeCount]}>
-                  {commentObject.reaction_count}
+                  {commentObject.user_reaction !== null
+                    ? commentObject.reaction_count + (liked ? 0 : -1)
+                    : commentObject.reaction_count + (liked ? 1 : 0)}
                 </Text>
                 <Text style={styles.date_time}>Likes</Text>
               </TouchableOpacity>
diff --git a/src/components/common/LikeButton.tsx b/src/components/common/LikeButton.tsx
index 43b3ac37..81383eca 100644
--- a/src/components/common/LikeButton.tsx
+++ b/src/components/common/LikeButton.tsx
@@ -1,28 +1,27 @@
-import React, {useState} from 'react';
+import React from 'react';
 import {Image, ImageStyle, StyleSheet, TouchableOpacity} from 'react-native';
 import {normalize} from '../../utils';
 
 interface LikeButtonProps {
   onPress: () => void;
   style: ImageStyle;
-  initialLikeState: boolean;
+  liked: boolean;
+  setLiked: (liked: boolean) => void;
 }
 const LikeButton: React.FC<LikeButtonProps> = ({
   onPress,
   style,
-  initialLikeState,
+  liked,
+  setLiked,
 }) => {
-  const [filled, setFilled] = useState(initialLikeState);
-  const uri = filled
+  const uri = liked
     ? require('../../assets/images/heart-filled.png')
     : require('../../assets/images/heart-outlined.png');
   return (
     <TouchableOpacity
       onPress={() => {
-        if (filled === initialLikeState) {
-          setFilled(!filled);
-          onPress();
-        }
+        setLiked(!liked);
+        onPress();
       }}>
       <Image style={[styles.image, style]} source={uri} />
     </TouchableOpacity>
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
index ad8f14ac..6d71ce9c 100644
--- a/src/services/CommentService.ts
+++ b/src/services/CommentService.ts
@@ -136,6 +136,7 @@ export const deleteComment = async (id: string, isThread: boolean) => {
  */
 export const handleLikeUnlikeComment = async (
   comment: CommentType | CommentThreadType,
+  liked: boolean,
 ) => {
   try {
     const isReply = 'parent_comment' in comment;
@@ -143,7 +144,7 @@ export const handleLikeUnlikeComment = async (
     let url = isReply
       ? COMMENT_REACTIONS_REPLY_ENDPOINT
       : COMMENT_REACTIONS_ENDPOINT;
-    if (comment.user_reaction !== null) {
+    if (liked) {
       // unlike a comment
       url += `${comment.comment_id}/?reaction_type=LIKE`;
       const response = await fetch(url, {
-- 
cgit v1.2.3-70-g09d2

