From 2ddd29120980ebced560dac09bbe270dc4aee0d1 Mon Sep 17 00:00:00 2001
From: Brian Kim <brian@tagg.id>
Date: Wed, 9 Jun 2021 09:24:00 +0900
Subject: Create separate pill component

---
 src/components/notifications/NotificationPill.tsx | 202 ++++++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 src/components/notifications/NotificationPill.tsx

(limited to 'src/components/notifications/NotificationPill.tsx')

diff --git a/src/components/notifications/NotificationPill.tsx b/src/components/notifications/NotificationPill.tsx
new file mode 100644
index 00000000..7017d2e7
--- /dev/null
+++ b/src/components/notifications/NotificationPill.tsx
@@ -0,0 +1,202 @@
+import React, {useEffect, useState, useRef} from 'react';
+import {Image, StyleSheet, Text, View} from 'react-native';
+import LinearGradient from 'react-native-linear-gradient';
+import {SCREEN_WIDTH, isIPhoneX, numberWithCommas} from '../../utils';
+import {
+  NOTIFICATION_ICON_GRADIENT,
+  CHIN_HEIGHT,
+  NAV_BAR_HEIGHT,
+} from '../../constants';
+import {getNotificationsUnreadCount} from '../../services';
+import {normalize} from 'react-native-elements';
+import PillIcon4 from '../../assets/images/Group 479.svg';
+
+interface NotificationPillProps {
+  showIcon: boolean;
+}
+
+export const NotificationPill: React.FC<NotificationPillProps> = ({
+  showIcon,
+}) => {
+  const [iconStart, setIconStart] = useState<number[]>([0, -100]);
+  const [tipStart, setTipStart] = useState<number[]>([0, -100]);
+  const [notificationSets, setNotificationSets] = useState({});
+  const [timeCount, setTimeCount] = useState<boolean>(false);
+  const [timeOut, setTimeOut] = useState<boolean>(false);
+  const iconRef = useRef(null);
+  const tipRef = useRef(null);
+  const pillTip = require('../../assets/images/purple-tip.png');
+
+  const navBarPos = 20;
+
+  // If there are notifications, determines the size of the pill
+  // and sets points for correct placement
+  useEffect(() => {
+    setTimeout(() => {
+      if (iconRef.current) {
+        iconRef.current.measure(
+          (
+            _fx: number,
+            _fy: number,
+            width: number,
+            height: number,
+            _px: number,
+            _py: number,
+          ) => {
+            if (tipRef.current) {
+              tipRef.current.measure(
+                (
+                  __fx: number,
+                  __fy: number,
+                  width2: number,
+                  __height: number,
+                  __px: number,
+                  __py: number,
+                ) => {
+                  const x = SCREEN_WIDTH / 2 - width / 2;
+                  const y = isIPhoneX()
+                    ? CHIN_HEIGHT + NAV_BAR_HEIGHT + navBarPos
+                    : NAV_BAR_HEIGHT + navBarPos;
+                  setIconStart([x, y]);
+                  setTipStart([width / 2 - width2 / 2, height - 1]);
+                  setTimeCount(true);
+                },
+              );
+            }
+          },
+        );
+      } else {
+      }
+    }, 100);
+  }, [notificationSets, iconRef, tipRef]);
+
+  // Used so that pill disappears after 5 seconds
+  useEffect(() => {
+    if (timeCount) {
+      setTimeout(() => {
+        setTimeOut(true);
+      }, 5000);
+    }
+  }, [timeCount]);
+
+  // Gets data from backend to check for unreads
+  useEffect(() => {
+    const getCount = async () => {
+      const data = await getNotificationsUnreadCount();
+      setTimeout(() => {
+        setNotificationSets(data);
+      }, 100);
+    };
+
+    getCount();
+  }, []);
+
+  return (
+    <>
+      {notificationSets &&
+        Object.keys(notificationSets).length !== 0 &&
+        showIcon &&
+        !timeOut && (
+          <View
+            style={[
+              styles.purpleContainer,
+              {bottom: iconStart[1], left: iconStart[0]},
+            ]}
+            ref={iconRef}>
+            <LinearGradient
+              colors={NOTIFICATION_ICON_GRADIENT}
+              style={styles.iconPurple}>
+              {notificationSets.CMT && (
+                <>
+                  <Image
+                    source={require('../../assets/images/pill-icon-1.png')}
+                    style={styles.indicationIcon}
+                  />
+                  <Text style={styles.text}>
+                    {numberWithCommas(notificationSets.CMT)}
+                  </Text>
+                </>
+              )}
+              {notificationSets.FR_REQ && (
+                <>
+                  <Image
+                    source={require('../../assets/images/pill-icon-2.png')}
+                    style={styles.indicationIcon}
+                  />
+                  <Text style={styles.text}>
+                    {numberWithCommas(notificationSets.FR_REQ)}
+                  </Text>
+                </>
+              )}
+              {notificationSets.P_VIEW && (
+                <>
+                  <Image
+                    source={require('../../assets/images/pill-icon-3.png')}
+                    style={styles.indicationIcon}
+                  />
+                  <Text style={styles.text}>
+                    {numberWithCommas(notificationSets.P_VIEW)}
+                  </Text>
+                </>
+              )}
+              {notificationSets.MOM_TAG && (
+                <>
+                  <PillIcon4 style={styles.indicationIcon} />
+                  <Text style={styles.text}>
+                    {numberWithCommas(notificationSets.MOM_TAG)}
+                  </Text>
+                </>
+              )}
+            </LinearGradient>
+            <Image
+              style={[styles.tip, {top: tipStart[1], left: tipStart[0]}]}
+              source={pillTip}
+              ref={tipRef}
+            />
+          </View>
+        )}
+    </>
+  );
+};
+
+const styles = StyleSheet.create({
+  purpleContainer: {
+    flex: 1,
+    justifyContent: 'center',
+    position: 'absolute',
+    zIndex: 999,
+  },
+  iconPurple: {
+    padding: 5,
+    borderRadius: 15,
+    flex: 1,
+    flexDirection: 'row',
+    alignItems: 'center',
+  },
+  text: {
+    margin: 2,
+    color: 'white',
+    fontSize: normalize(10),
+    justifyContent: 'center',
+    alignItems: 'center',
+    marginRight: 5,
+  },
+  tip: {
+    position: 'absolute',
+    zIndex: 999,
+    height: 12,
+    flex: 1,
+    resizeMode: 'contain',
+  },
+  indicationIcon: {
+    height: 14,
+    width: 14,
+    margin: 2,
+    marginLeft: 5,
+  },
+  svgIndicationIcon: {
+    height: 14,
+    width: 14,
+    margin: 3,
+  },
+});
-- 
cgit v1.2.3-70-g09d2


From 93796732be3f5070c0a124d29533396f79736c83 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 9 Jun 2021 17:37:40 -0400
Subject: Cleanup code

---
 src/components/notifications/NotificationPill.tsx | 15 +++++++++++----
 src/services/NotificationService.ts               | 10 ++--------
 src/types/types.ts                                |  4 +++-
 3 files changed, 16 insertions(+), 13 deletions(-)

(limited to 'src/components/notifications/NotificationPill.tsx')

diff --git a/src/components/notifications/NotificationPill.tsx b/src/components/notifications/NotificationPill.tsx
index 7017d2e7..01622a6f 100644
--- a/src/components/notifications/NotificationPill.tsx
+++ b/src/components/notifications/NotificationPill.tsx
@@ -20,7 +20,12 @@ export const NotificationPill: React.FC<NotificationPillProps> = ({
 }) => {
   const [iconStart, setIconStart] = useState<number[]>([0, -100]);
   const [tipStart, setTipStart] = useState<number[]>([0, -100]);
-  const [notificationSets, setNotificationSets] = useState({});
+  const [notificationSets, setNotificationSets] = useState<{
+    CMT?: number;
+    FRD_REQ?: number;
+    P_VIEW?: number;
+    MOM_TAG?: number;
+  }>({});
   const [timeCount, setTimeCount] = useState<boolean>(false);
   const [timeOut, setTimeOut] = useState<boolean>(false);
   const iconRef = useRef(null);
@@ -84,7 +89,9 @@ export const NotificationPill: React.FC<NotificationPillProps> = ({
     const getCount = async () => {
       const data = await getNotificationsUnreadCount();
       setTimeout(() => {
-        setNotificationSets(data);
+        if (data) {
+          setNotificationSets(data);
+        }
       }, 100);
     };
 
@@ -117,14 +124,14 @@ export const NotificationPill: React.FC<NotificationPillProps> = ({
                   </Text>
                 </>
               )}
-              {notificationSets.FR_REQ && (
+              {notificationSets.FRD_REQ && (
                 <>
                   <Image
                     source={require('../../assets/images/pill-icon-2.png')}
                     style={styles.indicationIcon}
                   />
                   <Text style={styles.text}>
-                    {numberWithCommas(notificationSets.FR_REQ)}
+                    {numberWithCommas(notificationSets.FRD_REQ)}
                   </Text>
                 </>
               )}
diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts
index 2ffc85b2..ccaa9135 100644
--- a/src/services/NotificationService.ts
+++ b/src/services/NotificationService.ts
@@ -34,12 +34,7 @@ export const getNotificationsData: () => Promise<NotificationType[]> =
     }
   };
 
-export const getNotificationsUnreadCount: () => Promise<{
-  CMT?: number;
-  FRD_REQ?: number;
-  P_VIEW?: number;
-  MOM_TAG?: number;
-}> = async () => {
+export const getNotificationsUnreadCount = async () => {
   try {
     const token = await AsyncStorage.getItem('token');
     const response = await fetch(NOTIFICATIONS_COUNT_ENDPOINT, {
@@ -70,11 +65,10 @@ export const getNotificationsUnreadCount: () => Promise<{
       }
       return typedData;
     }
-    return [];
   } catch (error) {
     console.log('Unable to fetch notifications');
-    return [];
   }
+  return undefined;
 };
 
 export const setNotificationsReadDate: () => Promise<boolean> = async () => {
diff --git a/src/types/types.ts b/src/types/types.ts
index e54c2201..fd75ab50 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -254,7 +254,9 @@ export type TypeOfNotification =
   // notification_object is MomentType
   | 'MOM_TAG'
   // notification_object is undefined
-  | 'SYSTEM_MSG';
+  | 'SYSTEM_MSG'
+  // notification_object is undefined
+  | 'P_VIEW';
 
 export type UniversityBadge = {
   id: number;
-- 
cgit v1.2.3-70-g09d2


From 3680329b9cdee900e72666d3c3644b3bb13f27ba Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Fri, 11 Jun 2021 11:49:32 -0400
Subject: Change timing to 10 seconds

---
 src/components/notifications/NotificationPill.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/components/notifications/NotificationPill.tsx')

diff --git a/src/components/notifications/NotificationPill.tsx b/src/components/notifications/NotificationPill.tsx
index 01622a6f..525cd7fa 100644
--- a/src/components/notifications/NotificationPill.tsx
+++ b/src/components/notifications/NotificationPill.tsx
@@ -75,12 +75,12 @@ export const NotificationPill: React.FC<NotificationPillProps> = ({
     }, 100);
   }, [notificationSets, iconRef, tipRef]);
 
-  // Used so that pill disappears after 5 seconds
+  // Used so that pill disappears after 10 seconds
   useEffect(() => {
     if (timeCount) {
       setTimeout(() => {
         setTimeOut(true);
-      }, 5000);
+      }, 10000);
     }
   }, [timeCount]);
 
-- 
cgit v1.2.3-70-g09d2

