From 5c6bedb572556586d34b99384dac1cad3a153402 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 1 Jun 2021 16:41:18 -0400
Subject: Refactor to use action instead of util function

---
 src/components/common/BadgeDetailView.tsx | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

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

diff --git a/src/components/common/BadgeDetailView.tsx b/src/components/common/BadgeDetailView.tsx
index 6504300c..ee66aa15 100644
--- a/src/components/common/BadgeDetailView.tsx
+++ b/src/components/common/BadgeDetailView.tsx
@@ -7,9 +7,10 @@ import {useDispatch, useSelector} from 'react-redux';
 import CloseIcon from '../../assets/ionicons/close-outline.svg';
 import {BADGE_GRADIENT_FIRST} from '../../constants';
 import {BADGE_DATA} from '../../constants/badges';
+import {removeUserBadge} from '../../store/actions';
 import {RootState} from '../../store/rootreducer';
 import {ScreenType} from '../../types';
-import {getUniversityBadge, normalize, removeUserBadge} from '../../utils';
+import {getUniversityBadge, normalize} from '../../utils';
 
 interface BadgeDetailModalProps {
   userXId: string | undefined;
@@ -59,7 +60,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
   }, [badges]);
 
   const removeBadgeCell = async (badgeName: string) => {
-    await removeUserBadge(badges, badgeName, user.userId, dispatch);
+    dispatch(removeUserBadge(badgeName, user.userId));
   };
 
   const badgeEditCell = ({item: {id, name, badgeImage}}) => {
-- 
cgit v1.2.3-70-g09d2


From cc71a8ce5808b2f7c40423c1a731821105215984 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 1 Jun 2021 18:53:17 -0400
Subject: Cleanup code/logic, Update heading/subheading, Adjust styling

---
 src/components/common/BadgeDetailView.tsx | 68 ++++++++++++++++---------------
 src/components/profile/ProfileBadges.tsx  |  1 +
 2 files changed, 37 insertions(+), 32 deletions(-)

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

diff --git a/src/components/common/BadgeDetailView.tsx b/src/components/common/BadgeDetailView.tsx
index ee66aa15..85f0a0dc 100644
--- a/src/components/common/BadgeDetailView.tsx
+++ b/src/components/common/BadgeDetailView.tsx
@@ -5,12 +5,15 @@ import {TouchableOpacity} from 'react-native-gesture-handler';
 import LinearGradient from 'react-native-linear-gradient';
 import {useDispatch, useSelector} from 'react-redux';
 import CloseIcon from '../../assets/ionicons/close-outline.svg';
-import {BADGE_GRADIENT_FIRST} from '../../constants';
-import {BADGE_DATA} from '../../constants/badges';
+import {BADGE_GRADIENT_FIRST, BADGE_LIMIT} from '../../constants';
 import {removeUserBadge} from '../../store/actions';
 import {RootState} from '../../store/rootreducer';
-import {ScreenType} from '../../types';
-import {getUniversityBadge, normalize} from '../../utils';
+import {ScreenType, UniversityBadgeDisplayType} from '../../types';
+import {
+  badgesToDisplayBadges,
+  getUniversityBadge,
+  normalize,
+} from '../../utils';
 
 interface BadgeDetailModalProps {
   userXId: string | undefined;
@@ -35,35 +38,24 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
     userXId ? state.userX[screenType][userXId] : state.user,
   );
   const navigation = useNavigation();
-  const [selectedBadgesWithImage, setSelectedBadgesWithImage] = useState<any[]>(
-    [],
-  );
+  const [displayBadges, setDisplayBadges] = useState<
+    UniversityBadgeDisplayType[]
+  >([]);
+  const atLimit = badges.length >= BADGE_LIMIT;
 
   useEffect(() => {
-    let badgesWithImage = [];
-    badges.forEach((e) => {
-      const uniData = BADGE_DATA[e.university];
-      const categoryData = uniData.filter((u) => {
-        return u.title === e.category;
-      });
-      const badgeData = categoryData[0].data.filter((c) => {
-        return c.badgeName === e.name;
-      });
-      badgeData.forEach((c) => {
-        const obj = {...e, badgeImage: c.badgeImage};
-        badgesWithImage.push(obj);
-      });
-    });
-    setTimeout(() => {
-      setSelectedBadgesWithImage(badgesWithImage);
-    }, 250);
+    setDisplayBadges(badgesToDisplayBadges(badges));
   }, [badges]);
 
   const removeBadgeCell = async (badgeName: string) => {
     dispatch(removeUserBadge(badgeName, user.userId));
   };
 
-  const badgeEditCell = ({item: {id, name, badgeImage}}) => {
+  const badgeEditCell = ({
+    item: {id, name, img},
+  }: {
+    item: UniversityBadgeDisplayType;
+  }) => {
     return (
       <TouchableOpacity
         style={styles.badgeCellContainerStyles}
@@ -72,7 +64,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
           navigation.navigate('MutualBadgeHolders', {
             badge_id: id,
             badge_title: name,
-            badge_img: badgeImage,
+            badge_img: img,
           });
         }}>
         <View
@@ -89,7 +81,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
             <Image
               resizeMode="cover"
               style={styles.badgeImageStyles}
-              source={badgeImage}
+              source={img}
             />
           </LinearGradient>
           {isEditable && (
@@ -122,10 +114,20 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
   };
 
   const modalHeader = () => {
-    const heading = isEditable ? 'Edit your badges!' : userFullName;
-    const subheading = isEditable
-      ? 'Add or delete your badges'
-      : 'View badges to discover groups!';
+    let heading = '';
+    let subheading = '';
+    if (isEditable) {
+      if (atLimit) {
+        heading = 'You have reached your badge limit';
+        subheading = 'Remove a badge if you wish to add more';
+      } else {
+        heading = 'Edit your badges!';
+        subheading = 'Add or delete your badges';
+      }
+    } else {
+      heading = userFullName!;
+      subheading = 'View badges to discover groups!';
+    }
     return (
       <View>
         <Text style={styles.modalHeadingStyles}>{heading}</Text>
@@ -156,7 +158,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
             <FlatList
               contentContainerStyle={styles.modalListStyles}
               scrollEnabled={false}
-              data={selectedBadgesWithImage}
+              data={displayBadges}
               numColumns={3}
               renderItem={badgeEditCell}
               keyExtractor={(item) => item.id.toString()}
@@ -229,6 +231,8 @@ const styles = StyleSheet.create({
     fontSize: normalize(17),
     lineHeight: normalize(20.29),
     textAlign: 'center',
+    marginVertical: normalize(10),
+    marginTop: normalize(20),
   },
   modalSubheadingStyles: {
     fontWeight: '600',
diff --git a/src/components/profile/ProfileBadges.tsx b/src/components/profile/ProfileBadges.tsx
index 39e84705..089d9ea4 100644
--- a/src/components/profile/ProfileBadges.tsx
+++ b/src/components/profile/ProfileBadges.tsx
@@ -135,6 +135,7 @@ const styles = StyleSheet.create({
   badgeContainer: {
     width: '100%',
     justifyContent: 'space-between',
+    marginTop: 5,
     marginBottom: 15,
   },
   circle: {
-- 
cgit v1.2.3-70-g09d2


From 06c1e5674a2e77bfa22048b4d559949403d30e0e Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 2 Jun 2021 14:54:05 -0400
Subject: Improve util code

---
 src/components/common/BadgeDetailView.tsx |  2 +-
 src/components/profile/ProfileBadges.tsx  |  8 +++----
 src/screens/suggestedPeople/SPBody.tsx    |  2 +-
 src/utils/common.ts                       | 39 +++++++++++++++++--------------
 4 files changed, 28 insertions(+), 23 deletions(-)

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

diff --git a/src/components/common/BadgeDetailView.tsx b/src/components/common/BadgeDetailView.tsx
index 85f0a0dc..19f1e74d 100644
--- a/src/components/common/BadgeDetailView.tsx
+++ b/src/components/common/BadgeDetailView.tsx
@@ -44,7 +44,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
   const atLimit = badges.length >= BADGE_LIMIT;
 
   useEffect(() => {
-    setDisplayBadges(badgesToDisplayBadges(badges));
+    setDisplayBadges(badgesToDisplayBadges(badges, university));
   }, [badges]);
 
   const removeBadgeCell = async (badgeName: string) => {
diff --git a/src/components/profile/ProfileBadges.tsx b/src/components/profile/ProfileBadges.tsx
index aef52903..8e68dc46 100644
--- a/src/components/profile/ProfileBadges.tsx
+++ b/src/components/profile/ProfileBadges.tsx
@@ -1,15 +1,15 @@
 import {useNavigation} from '@react-navigation/core';
 import React, {FC, useEffect, useState} from 'react';
-import {Image, StyleSheet, Text, View} from 'react-native';
+import {StyleSheet, Text, View} from 'react-native';
 import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler';
 import {useSelector} from 'react-redux';
 import {BadgeIcon} from '..';
+import PlusIconImage from '../../assets/icons/plus-icon-thin.svg';
 import {BADGE_LIMIT} from '../../constants';
 import {RootState} from '../../store/rootReducer';
 import {ScreenType, UniversityBadgeDisplayType} from '../../types';
 import {badgesToDisplayBadges, normalize} from '../../utils';
 import BadgeDetailView from '../common/BadgeDetailView';
-import PlusIconImage from '../../assets/icons/plus-icon-thin.svg';
 
 interface ProfileBadgesProps {
   userXId: string | undefined;
@@ -18,7 +18,7 @@ interface ProfileBadgesProps {
 
 const ProfileBadges: React.FC<ProfileBadgesProps> = ({userXId, screenType}) => {
   const navigation = useNavigation();
-  const {badges, name} = useSelector((state: RootState) =>
+  const {badges, name, university} = useSelector((state: RootState) =>
     userXId ? state.userX[screenType][userXId].profile : state.user.profile,
   );
   const [displayBadges, setDisplayBadges] = useState<
@@ -28,7 +28,7 @@ const ProfileBadges: React.FC<ProfileBadgesProps> = ({userXId, screenType}) => {
   const isOwnProfile = userXId === undefined;
 
   useEffect(() => {
-    setDisplayBadges(badgesToDisplayBadges(badges));
+    setDisplayBadges(badgesToDisplayBadges(badges, university));
   }, [badges]);
 
   const PlusIcon: FC = () => (
diff --git a/src/screens/suggestedPeople/SPBody.tsx b/src/screens/suggestedPeople/SPBody.tsx
index c37b4c44..fea67950 100644
--- a/src/screens/suggestedPeople/SPBody.tsx
+++ b/src/screens/suggestedPeople/SPBody.tsx
@@ -49,7 +49,7 @@ const SPBody: React.FC<SPBodyProps> = ({
   >([]);
   const navigation = useNavigation();
   useEffect(() => {
-    setDisplayBadges(badgesToDisplayBadges(badges));
+    setDisplayBadges(badgesToDisplayBadges(badges, university));
   }, []);
 
   const FriendButton = () => {
diff --git a/src/utils/common.ts b/src/utils/common.ts
index 7e54eeaf..cfd9244a 100644
--- a/src/utils/common.ts
+++ b/src/utils/common.ts
@@ -1,6 +1,6 @@
 import AsyncStorage from '@react-native-community/async-storage';
 import moment from 'moment';
-import {Linking} from 'react-native';
+import {ImageSourcePropType, Linking} from 'react-native';
 import {getAll} from 'react-native-contacts';
 import {
   BADGE_DATA,
@@ -205,26 +205,31 @@ export const validateImageLink = async (url: string | undefined) => {
 };
 
 /**
- * Turns a list badges into display badges (with img) by looking up the img source
- * from our badge asset lookup constant.
+ * Turns a list of badges into display badges (just a badge with img) by
+ * looking up the img source from our badge asset lookup constant.
+ *
+ * WARNING: Assumes a small list of badges, complexity goes up exponentially.
+ *
  * @param badges list of university badges
+ * @param university university of which all the badges belong
  * @returns list of display badges
  */
-export const badgesToDisplayBadges = (badges: UniversityBadge[]) => {
-  const displayBadges: UniversityBadgeDisplayType[] = [];
-  badges.forEach((badge) => {
-    BADGE_DATA[badge.university].forEach((category) => {
-      if (category.title === badge.category) {
-        category.data.forEach((badgeInfo) => {
-          if (badgeInfo.badgeName === badge.name) {
-            displayBadges.push({
-              ...badge,
-              img: badgeInfo.badgeImage,
-            });
-          }
-        });
+export const badgesToDisplayBadges = (
+  badges: UniversityBadge[],
+  university: UniversityType,
+) => {
+  const badgeSet: Set<string> = new Set(badges.map((b) => b.category + b.name));
+  const badgeToImgMap: Record<string, ImageSourcePropType> = {};
+  BADGE_DATA[university].forEach((category) => {
+    category.data.forEach((badgeInfo) => {
+      const key = category.title + badgeInfo.badgeName;
+      if (badgeSet.has(key)) {
+        badgeToImgMap[key] = badgeInfo.badgeImage;
       }
     });
   });
-  return displayBadges;
+  return <UniversityBadgeDisplayType[]>badges.map((b) => ({
+    ...b,
+    img: badgeToImgMap[b.category + b.name],
+  }));
 };
-- 
cgit v1.2.3-70-g09d2

