From 68fcf7c533ba7612c94760b1171c506f64bfc0ae Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 1 Jun 2021 14:43:30 -0700 Subject: Filled out basic front-end, need to integrate with back-end --- src/routes/tabs/NavigationBar.tsx | 405 +++++++++++++++++++++++++++++++------- 1 file changed, 330 insertions(+), 75 deletions(-) (limited to 'src/routes') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 000ac614..0e08d834 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -1,12 +1,26 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import React, {Fragment, useEffect, useState} from 'react'; +import React, {Fragment, useEffect, useState, useRef} from 'react'; +import {Image, StyleSheet, Text, View} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import {ScreenType} from '../../types'; -import {haveUnreadNotifications} from '../../utils'; +import {ScreenType, NotificationType} from '../../types'; +import { + haveUnreadNotifications, + getUnreadNotifications, + SCREEN_WIDTH, + isIPhoneX, +} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; +import { + NOTIFICATION_ICON_GRADIENT, + CHIN_HEIGHT, + NAV_BAR_HEIGHT, +} from '../../constants'; +import {normalize} from 'react-native-elements'; +import {numberWithCommas} from '../../utils'; const Tabs = createBottomTabNavigator(); @@ -19,8 +33,47 @@ const NavigationBar: React.FC = () => { (state: RootState) => state, ); - const [unreadNotificationsPresent, setUnreadNotificationsPresent] = - useState(false); + const [unread, setUnread] = useState({ + CMT: 4, + FR_REQ: 5, + PR_V: 3, + TAG: 7, + }); + const [showIcon, setShowIcon] = useState(true); + const [iconStart, setIconStart] = useState([0, -100]); + const [tipStart, setTipStart] = useState([0, -100]); + const [complete, setComplete] = useState(false); + const [notificationSets, setNotificationSets] = useState({ + CMT: 412314213123, + FR_REQ: 52131, + PR_V: 3, + TAG: 712321, + }); + const [timeCount, setTimeCount] = useState(false); + const iconRef = useRef(null); + const tipRef = useRef(null); + const pillTip = require('../../assets/images/purple-tip.png'); + + const navBarPos = 20; + const tipSize = 8; + + const [ + unreadNotificationsPresent, + setUnreadNotificationsPresent, + ] = useState(false); + + const countNotifications = ( + notificationsList: NotificationType[], + values: string[], + ) => { + let outputNum = 0; + for (const n of notificationsList) { + if (values.includes(n.notification_type)) { + outputNum++; + } + } + return outputNum; + }; useEffect(() => { const determine = async () => { @@ -28,82 +81,284 @@ const NavigationBar: React.FC = () => { await haveUnreadNotifications(notifications), ); }; + // const establishUnread = async () => { + // setUnread(await getUnreadNotifications(notifications)); + // }; determine(); + // establishUnread(); }, [notifications]); + useEffect(() => { + setTimeout(() => { + console.log('notifications', notifications.length, 'unread', unread); + if (iconRef.current) { + iconRef.current.measure( + ( + _fx: number, + _fy: number, + width: number, + height: number, + _px: number, + _py: number, + ) => { + console.log('HERE 1'); + 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]); + setTimeout(() => { + setComplete(true); + console.log('HERE 2'); + }, 100); + setTimeCount(true); + }, + ); + } + }, + ); + } else { + console.log('ISSUE', iconRef.current); + } + }, 100); + }, [unread, iconRef, tipRef]); + + useEffect(() => { + if (timeCount) { + setTimeout(() => { + setShowIcon(false); + }, 5000); + } + }, [timeCount]); + + useEffect(() => { + setTimeout(() => { + console.log('complete', complete); + }, 100); + }, [complete]); + + useEffect(() => { + setTimeout(() => { + console.log('iconRef', iconRef); + }, 60000); + }); + return ( - ({ - tabBarIcon: ({focused}) => { - switch (route.name) { - case 'Home': - return ; - case 'Search': - return ; - case 'Upload': - return ; - case 'Notifications': - return ( - + {unread && Object.keys(unread).length !== 0 && showIcon && ( + + + {notificationSets.CMT && ( + <> + - ); - case 'Chat': - return ; - case 'Profile': - return ; - case 'SuggestedPeople': - return ( - - ); - default: - return ; - } - }, - })} - initialRouteName={isOnboardedUser ? 'Profile' : 'SuggestedPeople'} - tabBarOptions={{ - showLabel: false, - style: { - backgroundColor: 'transparent', - position: 'absolute', - borderTopWidth: 0, - left: 0, - right: 0, - bottom: '1%', - }, - }}> - - - - - - + + {numberWithCommas(notificationSets.CMT)} + + + )} + {notificationSets.FR_REQ && ( + <> + + + {numberWithCommas(notificationSets.FR_REQ)} + + + )} + {notificationSets.PR_V && ( + <> + + + {numberWithCommas(notificationSets.PR_V)} + + + )} + {notificationSets.TAG && ( + <> + + + {numberWithCommas(notificationSets.TAG)} + + + )} + + + + )} + ({ + tabBarIcon: ({focused}) => { + switch (route.name) { + case 'Home': + return ; + case 'Search': + return ; + case 'Upload': + return ; + case 'Notifications': + return ( + + ); + case 'Chat': + return ; + case 'Profile': + return ; + case 'SuggestedPeople': + return ( + + ); + default: + return ; + } + }, + })} + initialRouteName={isOnboardedUser ? 'Profile' : 'SuggestedPeople'} + tabBarOptions={{ + showLabel: false, + style: { + backgroundColor: 'transparent', + position: 'absolute', + borderTopWidth: 0, + left: 0, + right: 0, + bottom: '1%', + }, + }}> + { + setShowIcon(true); + }, + }} + /> + { + setShowIcon(true); + }, + }} + /> + { + setShowIcon(false); + }, + }} + /> + { + setShowIcon(true); + }, + }} + /> + { + setShowIcon(true); + }, + }} + /> + + ); }; +const styles = StyleSheet.create({ + purpleContainer: { + // borderWidth: 1, + flex: 1, + justifyContent: 'center', + position: 'absolute', + zIndex: 999, + // flexDirection: 'row', + // bottom: 50, + // height: normalize(20), + }, + iconPurple: { + padding: 5, + borderRadius: 15, + flex: 1, + flexDirection: 'row', + // justifyContent: 'center', + // alignContent: 'center', + alignItems: 'center', + }, + text: { + margin: 2, + color: 'white', + fontSize: normalize(10), + justifyContent: 'center', + alignItems: 'center', + }, + tip: { + // borderWidth: 1, + position: 'absolute', + zIndex: 999, + height: 12, + // aspectRatio: 12 / 8, + flex: 1, + resizeMode: 'contain', + }, + indicationIcon: { + height: 15, + width: 15, + margin: 2, + }, +}); + export default NavigationBar; -- cgit v1.2.3-70-g09d2 From 43a420ec518f122b684bb9d2f4dd4043bf65d2d2 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Wed, 2 Jun 2021 11:58:59 -0700 Subject: Some cosmetic changes --- src/assets/images/Group 479.jpg | Bin 0 -> 753 bytes src/assets/images/Group 479.svg | 5 ++ src/routes/tabs/NavigationBar.tsx | 185 +++++++++++++++++--------------------- 3 files changed, 87 insertions(+), 103 deletions(-) create mode 100644 src/assets/images/Group 479.jpg create mode 100644 src/assets/images/Group 479.svg (limited to 'src/routes') diff --git a/src/assets/images/Group 479.jpg b/src/assets/images/Group 479.jpg new file mode 100644 index 00000000..74abad92 Binary files /dev/null and b/src/assets/images/Group 479.jpg differ diff --git a/src/assets/images/Group 479.svg b/src/assets/images/Group 479.svg new file mode 100644 index 00000000..4e1eee01 --- /dev/null +++ b/src/assets/images/Group 479.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 0e08d834..1693d057 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -6,13 +6,8 @@ import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import {ScreenType, NotificationType} from '../../types'; -import { - haveUnreadNotifications, - getUnreadNotifications, - SCREEN_WIDTH, - isIPhoneX, -} from '../../utils'; +import {ScreenType} from '../../types'; +import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; import { NOTIFICATION_ICON_GRADIENT, @@ -21,6 +16,7 @@ import { } from '../../constants'; import {normalize} from 'react-native-elements'; import {numberWithCommas} from '../../utils'; +import PillIcon4 from '../../assets/images/Group 479.svg'; const Tabs = createBottomTabNavigator(); @@ -32,13 +28,6 @@ const NavigationBar: React.FC = () => { const {notifications: {notifications} = NO_NOTIFICATIONS} = useSelector( (state: RootState) => state, ); - - const [unread, setUnread] = useState({ - CMT: 4, - FR_REQ: 5, - PR_V: 3, - TAG: 7, - }); const [showIcon, setShowIcon] = useState(true); const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); @@ -50,31 +39,18 @@ const NavigationBar: React.FC = () => { TAG: 712321, }); const [timeCount, setTimeCount] = useState(false); + const [timeOut, setTimeOut] = useState(false); const iconRef = useRef(null); const tipRef = useRef(null); const pillTip = require('../../assets/images/purple-tip.png'); const navBarPos = 20; - const tipSize = 8; const [ unreadNotificationsPresent, setUnreadNotificationsPresent, ] = useState(false); - const countNotifications = ( - notificationsList: NotificationType[], - values: string[], - ) => { - let outputNum = 0; - for (const n of notificationsList) { - if (values.includes(n.notification_type)) { - outputNum++; - } - } - return outputNum; - }; - useEffect(() => { const determine = async () => { setUnreadNotificationsPresent( @@ -90,7 +66,12 @@ const NavigationBar: React.FC = () => { useEffect(() => { setTimeout(() => { - console.log('notifications', notifications.length, 'unread', unread); + console.log( + 'notifications', + notifications.length, + 'unread', + notificationSets, + ); if (iconRef.current) { iconRef.current.measure( ( @@ -132,12 +113,12 @@ const NavigationBar: React.FC = () => { console.log('ISSUE', iconRef.current); } }, 100); - }, [unread, iconRef, tipRef]); + }, [notificationSets, iconRef, tipRef]); useEffect(() => { if (timeCount) { setTimeout(() => { - setShowIcon(false); + setTimeOut(true); }, 5000); } }, [timeCount]); @@ -156,68 +137,68 @@ const NavigationBar: React.FC = () => { return ( <> - {unread && Object.keys(unread).length !== 0 && showIcon && ( - - - {notificationSets.CMT && ( - <> - - - {numberWithCommas(notificationSets.CMT)} - - - )} - {notificationSets.FR_REQ && ( - <> - - - {numberWithCommas(notificationSets.FR_REQ)} - - - )} - {notificationSets.PR_V && ( - <> - - - {numberWithCommas(notificationSets.PR_V)} - - - )} - {notificationSets.TAG && ( - <> - - - {numberWithCommas(notificationSets.TAG)} - - - )} - - - - )} + {notificationSets && + Object.keys(notificationSets).length !== 0 && + showIcon && + !timeOut && ( + + + {notificationSets.CMT && ( + <> + + + {numberWithCommas(notificationSets.CMT)} + + + )} + {notificationSets.FR_REQ && ( + <> + + + {numberWithCommas(notificationSets.FR_REQ)} + + + )} + {notificationSets.PR_V && ( + <> + + + {numberWithCommas(notificationSets.PR_V)} + + + )} + {notificationSets.TAG && ( + <> + + + {numberWithCommas(notificationSets.TAG)} + + + )} + + + + )} ({ tabBarIcon: ({focused}) => { @@ -320,22 +301,16 @@ const NavigationBar: React.FC = () => { const styles = StyleSheet.create({ purpleContainer: { - // borderWidth: 1, flex: 1, justifyContent: 'center', position: 'absolute', zIndex: 999, - // flexDirection: 'row', - // bottom: 50, - // height: normalize(20), }, iconPurple: { padding: 5, borderRadius: 15, flex: 1, flexDirection: 'row', - // justifyContent: 'center', - // alignContent: 'center', alignItems: 'center', }, text: { @@ -344,21 +319,25 @@ const styles = StyleSheet.create({ fontSize: normalize(10), justifyContent: 'center', alignItems: 'center', + marginRight: 10, }, tip: { - // borderWidth: 1, position: 'absolute', zIndex: 999, height: 12, - // aspectRatio: 12 / 8, flex: 1, resizeMode: 'contain', }, indicationIcon: { - height: 15, - width: 15, + height: 14, + width: 14, margin: 2, }, + svgIndicationIcon: { + height: 14, + width: 14, + margin: 3, + }, }); export default NavigationBar; -- cgit v1.2.3-70-g09d2 From 19630f8bc3b4b53244007e08436c5be67a4d7ef1 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Mon, 7 Jun 2021 15:58:08 +0900 Subject: Basic integration with API --- src/constants/api.ts | 1 + src/routes/tabs/NavigationBar.tsx | 31 ++++++------ src/services/NotificationService.ts | 99 +++++++++++++++++++++++++++---------- 3 files changed, 91 insertions(+), 40 deletions(-) (limited to 'src/routes') diff --git a/src/constants/api.ts b/src/constants/api.ts index f02ee407..8d2e1a1e 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -45,6 +45,7 @@ export const BLOCK_USER_ENDPOINT: string = API_URL + 'block/'; export const PASSWORD_RESET_ENDPOINT: string = API_URL + 'password-reset/'; export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; +export const NOTIFICATIONS_COUNT_ENDPOINT: string = API_URL + 'notifications/unread_count/' export const DISCOVER_ENDPOINT: string = API_URL + 'discover/'; export const SEARCH_BUTTONS_ENDPOPINT: string = DISCOVER_ENDPOINT + 'search_buttons/'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 1693d057..3359fc0d 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -6,6 +6,7 @@ import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; +import {getNotificationsUnreadCount} from '../../services'; import {ScreenType} from '../../types'; import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; @@ -32,12 +33,7 @@ const NavigationBar: React.FC = () => { const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); const [complete, setComplete] = useState(false); - const [notificationSets, setNotificationSets] = useState({ - CMT: 412314213123, - FR_REQ: 52131, - PR_V: 3, - TAG: 712321, - }); + const [notificationSets, setNotificationSets] = useState({}); const [timeCount, setTimeCount] = useState(false); const [timeOut, setTimeOut] = useState(false); const iconRef = useRef(null); @@ -130,10 +126,17 @@ const NavigationBar: React.FC = () => { }, [complete]); useEffect(() => { - setTimeout(() => { - console.log('iconRef', iconRef); - }, 60000); - }); + // setTimeout(() => { + // console.log('iconRef', iconRef); + // }, 60000); + + const getCount = async () => { + const data = await getNotificationsUnreadCount(); + setNotificationSets(data); + }; + + getCount(); + }, []); return ( <> @@ -172,22 +175,22 @@ const NavigationBar: React.FC = () => { )} - {notificationSets.PR_V && ( + {notificationSets.P_VIEW && ( <> - {numberWithCommas(notificationSets.PR_V)} + {numberWithCommas(notificationSets.P_VIEW)} )} - {notificationSets.TAG && ( + {notificationSets.MOM_TAG && ( <> - {numberWithCommas(notificationSets.TAG)} + {numberWithCommas(notificationSets.MOM_TAG)} )} diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts index c5c843f5..92f1cdd1 100644 --- a/src/services/NotificationService.ts +++ b/src/services/NotificationService.ts @@ -1,31 +1,78 @@ import AsyncStorage from '@react-native-community/async-storage'; -import {NOTIFICATIONS_ENDPOINT} from '../constants'; +import { + NOTIFICATIONS_ENDPOINT, + NOTIFICATIONS_COUNT_ENDPOINT, +} from '../constants'; import {NotificationType} from '../types'; -export const getNotificationsData: () => Promise = - async () => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(NOTIFICATIONS_ENDPOINT, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - if (response.status === 200) { - const data: any[] = await response.json(); - let typedData: NotificationType[] = []; - for (const o of data) { - typedData.push({ - ...o.notification, - unread: false, - }); - } - return typedData; +export const getNotificationsData: () => Promise< + NotificationType[] +> = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_ENDPOINT, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data: any[] = await response.json(); + let typedData: NotificationType[] = []; + for (const o of data) { + typedData.push({ + ...o.notification, + unread: false, + }); } - return []; - } catch (error) { - console.log('Unable to fetch notifications'); - return []; + return typedData; } - }; + return []; + } catch (error) { + console.log('Unable to fetch notifications'); + return []; + } +}; + +export const getNotificationsUnreadCount: () => Promise<{ + CMT?: number; + FRD_REQ?: number; + P_VIEW?: number; + MOM_TAG?: number; +}> = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_COUNT_ENDPOINT, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data: any = await response.json(); + const typedData: { + CMT?: number; + FRD_REQ?: number; + P_VIEW?: number; + MOM_TAG?: number; + } = {}; + if (data.CMT && data.CMT > 0) { + typedData.CMT = data.CMT; + } + if (data.FRD_REQ && data.FRD_REQ > 0) { + typedData.FRD_REQ = data.FRD_REQ; + } + if (data.P_VIEW && data.P_VIEW > 0) { + typedData.P_VIEW = data.P_VIEW; + } + if (data.MOM_TAG && data.MOM_TAG > 0) { + typedData.MOM_TAG = data.MOM_TAG; + } + return typedData; + } + return []; + } catch (error) { + console.log('Unable to fetch notifications'); + return []; + } +}; -- cgit v1.2.3-70-g09d2 From 2ab67a10be5305ed54464688c4147a493bfed8f6 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 08:14:37 +0900 Subject: Clean up --- src/routes/tabs/NavigationBar.tsx | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) (limited to 'src/routes') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 3359fc0d..4b291023 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -32,7 +32,6 @@ const NavigationBar: React.FC = () => { const [showIcon, setShowIcon] = useState(true); const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); - const [complete, setComplete] = useState(false); const [notificationSets, setNotificationSets] = useState({}); const [timeCount, setTimeCount] = useState(false); const [timeOut, setTimeOut] = useState(false); @@ -53,21 +52,11 @@ const NavigationBar: React.FC = () => { await haveUnreadNotifications(notifications), ); }; - // const establishUnread = async () => { - // setUnread(await getUnreadNotifications(notifications)); - // }; determine(); - // establishUnread(); }, [notifications]); useEffect(() => { setTimeout(() => { - console.log( - 'notifications', - notifications.length, - 'unread', - notificationSets, - ); if (iconRef.current) { iconRef.current.measure( ( @@ -78,7 +67,6 @@ const NavigationBar: React.FC = () => { _px: number, _py: number, ) => { - console.log('HERE 1'); if (tipRef.current) { tipRef.current.measure( ( @@ -95,10 +83,6 @@ const NavigationBar: React.FC = () => { : NAV_BAR_HEIGHT + navBarPos; setIconStart([x, y]); setTipStart([width / 2 - width2 / 2, height - 1]); - setTimeout(() => { - setComplete(true); - console.log('HERE 2'); - }, 100); setTimeCount(true); }, ); @@ -106,7 +90,6 @@ const NavigationBar: React.FC = () => { }, ); } else { - console.log('ISSUE', iconRef.current); } }, 100); }, [notificationSets, iconRef, tipRef]); @@ -120,19 +103,12 @@ const NavigationBar: React.FC = () => { }, [timeCount]); useEffect(() => { - setTimeout(() => { - console.log('complete', complete); - }, 100); - }, [complete]); - - useEffect(() => { - // setTimeout(() => { - // console.log('iconRef', iconRef); - // }, 60000); - const getCount = async () => { - const data = await getNotificationsUnreadCount(); - setNotificationSets(data); + // const data = await getNotificationsUnreadCount(); + const data = {}; + setTimeout(() => { + setNotificationSets(data); + }, 100); }; getCount(); -- cgit v1.2.3-70-g09d2 From 9c48eeee298eacf781f25907c231f503edb4c5a4 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 18:17:21 +0900 Subject: Integrate with backend --- src/constants/api.ts | 3 +- src/routes/tabs/NavigationBar.tsx | 34 ++++++++++-------- src/services/NotificationService.ts | 72 +++++++++++++++++++++++-------------- 3 files changed, 67 insertions(+), 42 deletions(-) (limited to 'src/routes') diff --git a/src/constants/api.ts b/src/constants/api.ts index 8d2e1a1e..b55489d9 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -45,7 +45,8 @@ export const BLOCK_USER_ENDPOINT: string = API_URL + 'block/'; export const PASSWORD_RESET_ENDPOINT: string = API_URL + 'password-reset/'; export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; -export const NOTIFICATIONS_COUNT_ENDPOINT: string = API_URL + 'notifications/unread_count/' +export const NOTIFICATIONS_COUNT_ENDPOINT: string = API_URL + 'notifications/unread_count/'; +export const NOTIFICATIONS_DATE: string = API_URL + 'notifications/seen/'; export const DISCOVER_ENDPOINT: string = API_URL + 'discover/'; export const SEARCH_BUTTONS_ENDPOPINT: string = DISCOVER_ENDPOINT + 'search_buttons/'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 4b291023..77131098 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -6,7 +6,10 @@ import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import {getNotificationsUnreadCount} from '../../services'; +import { + getNotificationsUnreadCount, + setNotificationsReadDate, +} from '../../services'; import {ScreenType} from '../../types'; import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; @@ -41,10 +44,8 @@ const NavigationBar: React.FC = () => { const navBarPos = 20; - const [ - unreadNotificationsPresent, - setUnreadNotificationsPresent, - ] = useState(false); + const [unreadNotificationsPresent, setUnreadNotificationsPresent] = + useState(false); useEffect(() => { const determine = async () => { @@ -56,6 +57,7 @@ const NavigationBar: React.FC = () => { }, [notifications]); useEffect(() => { + console.log('notifications', notificationSets); setTimeout(() => { if (iconRef.current) { iconRef.current.measure( @@ -94,18 +96,18 @@ const NavigationBar: React.FC = () => { }, 100); }, [notificationSets, iconRef, tipRef]); - useEffect(() => { - if (timeCount) { - setTimeout(() => { - setTimeOut(true); - }, 5000); - } - }, [timeCount]); + // useEffect(() => { + // if (timeCount) { + // setTimeout(() => { + // setTimeOut(true); + // }, 5000); + // } + // }, [timeCount]); useEffect(() => { const getCount = async () => { - // const data = await getNotificationsUnreadCount(); - const data = {}; + const data = await getNotificationsUnreadCount(); + // const data = {}; setTimeout(() => { setNotificationSets(data); }, 100); @@ -250,6 +252,7 @@ const NavigationBar: React.FC = () => { listeners={{ tabPress: (_) => { setShowIcon(false); + setNotificationsReadDate(); }, }} /> @@ -298,7 +301,7 @@ const styles = StyleSheet.create({ fontSize: normalize(10), justifyContent: 'center', alignItems: 'center', - marginRight: 10, + marginRight: 5, }, tip: { position: 'absolute', @@ -311,6 +314,7 @@ const styles = StyleSheet.create({ height: 14, width: 14, margin: 2, + marginLeft: 5, }, svgIndicationIcon: { height: 14, diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts index 92f1cdd1..3c0245a5 100644 --- a/src/services/NotificationService.ts +++ b/src/services/NotificationService.ts @@ -2,37 +2,37 @@ import AsyncStorage from '@react-native-community/async-storage'; import { NOTIFICATIONS_ENDPOINT, NOTIFICATIONS_COUNT_ENDPOINT, + NOTIFICATIONS_DATE, } from '../constants'; import {NotificationType} from '../types'; -export const getNotificationsData: () => Promise< - NotificationType[] -> = async () => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(NOTIFICATIONS_ENDPOINT, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - if (response.status === 200) { - const data: any[] = await response.json(); - let typedData: NotificationType[] = []; - for (const o of data) { - typedData.push({ - ...o.notification, - unread: false, - }); +export const getNotificationsData: () => Promise = + async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_ENDPOINT, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data: any[] = await response.json(); + let typedData: NotificationType[] = []; + for (const o of data) { + typedData.push({ + ...o.notification, + unread: false, + }); + } + return typedData; } - return typedData; + return []; + } catch (error) { + console.log('Unable to fetch notifications'); + return []; } - return []; - } catch (error) { - console.log('Unable to fetch notifications'); - return []; - } -}; + }; export const getNotificationsUnreadCount: () => Promise<{ CMT?: number; @@ -76,3 +76,23 @@ export const getNotificationsUnreadCount: () => Promise<{ return []; } }; + +export const setNotificationsReadDate: () => Promise = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_DATE, { + method: 'POST', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 204) { + return true; + } else { + return false; + } + } catch (error) { + console.log('Unable to fetch notifications'); + return false; + } +}; -- cgit v1.2.3-70-g09d2 From 4636694489159c5f9edf0238460bde08e2219f80 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 18:18:14 +0900 Subject: Remove some excess comments --- src/routes/tabs/NavigationBar.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/routes') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 77131098..fa129a23 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -96,13 +96,13 @@ const NavigationBar: React.FC = () => { }, 100); }, [notificationSets, iconRef, tipRef]); - // useEffect(() => { - // if (timeCount) { - // setTimeout(() => { - // setTimeOut(true); - // }, 5000); - // } - // }, [timeCount]); + useEffect(() => { + if (timeCount) { + setTimeout(() => { + setTimeOut(true); + }, 5000); + } + }, [timeCount]); useEffect(() => { const getCount = async () => { -- cgit v1.2.3-70-g09d2 From 2f66fec878e9bba15ac7f2397820bb48d3f167bb Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 18:21:26 +0900 Subject: Add documentation --- src/routes/tabs/NavigationBar.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/routes') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index fa129a23..e962c8da 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -47,6 +47,8 @@ const NavigationBar: React.FC = () => { const [unreadNotificationsPresent, setUnreadNotificationsPresent] = useState(false); + // Prior to pill inclusion, determines if notification bell + // should have purple dot useEffect(() => { const determine = async () => { setUnreadNotificationsPresent( @@ -56,8 +58,9 @@ const NavigationBar: React.FC = () => { determine(); }, [notifications]); + // If there are notifications, determines the size of the pill + // and sets points for correct placement useEffect(() => { - console.log('notifications', notificationSets); setTimeout(() => { if (iconRef.current) { iconRef.current.measure( @@ -96,6 +99,7 @@ const NavigationBar: React.FC = () => { }, 100); }, [notificationSets, iconRef, tipRef]); + // Used so that pill disappears after 5 seconds useEffect(() => { if (timeCount) { setTimeout(() => { @@ -104,10 +108,10 @@ const NavigationBar: React.FC = () => { } }, [timeCount]); + // Gets data from backend to check for unreads useEffect(() => { const getCount = async () => { const data = await getNotificationsUnreadCount(); - // const data = {}; setTimeout(() => { setNotificationSets(data); }, 100); @@ -229,6 +233,8 @@ const NavigationBar: React.FC = () => { name="SuggestedPeople" component={MainStackScreen} initialParams={{screenType: ScreenType.SuggestedPeople}} + // Added these to as a way to close pill when on + // notification page listeners={{ tabPress: (_) => { setShowIcon(true); @@ -252,6 +258,7 @@ const NavigationBar: React.FC = () => { listeners={{ tabPress: (_) => { setShowIcon(false); + // Updates backend's date of reading notifications setNotificationsReadDate(); }, }} -- cgit v1.2.3-70-g09d2 From 96a80c53fcc0b5815b56f0ed0b48d152a6c6e2a4 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Tue, 8 Jun 2021 11:33:13 -0400 Subject: Cleanup linter warnings --- src/components/moments/MomentPost.tsx | 6 ++---- src/components/moments/MomentPostContent.tsx | 1 - src/routes/main/MainStackScreen.tsx | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src/routes') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index b97b8034..1f363052 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -1,11 +1,11 @@ import React, {useEffect, useState} from 'react'; -import {StyleSheet, View} from 'react-native'; +import {StyleSheet} from 'react-native'; import {useSelector} from 'react-redux'; import {MomentPostContent, MomentPostHeader} from '.'; import {deleteMomentTag, loadMomentTags} from '../../services'; import {RootState} from '../../store/rootReducer'; import {MomentTagType, MomentType, ScreenType} from '../../types'; -import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; +import {SCREEN_HEIGHT} from '../../utils'; interface MomentPostProps { item: MomentType; @@ -13,8 +13,6 @@ interface MomentPostProps { screenType: ScreenType; } -const ITEM_HEIGHT = SCREEN_HEIGHT * 0.9; - const MomentPost: React.FC = ({item, userXId, screenType}) => { const {userId: loggedInUserId, username: loggedInUsername} = useSelector( (state: RootState) => state.user.user, diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index de31ad55..dcad9aca 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -11,7 +11,6 @@ import { getTimePosted, navigateToProfile, normalize, - SCREEN_HEIGHT, SCREEN_WIDTH, } from '../../utils'; import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments'; diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx index f6a012d6..3be2ff28 100644 --- a/src/routes/main/MainStackScreen.tsx +++ b/src/routes/main/MainStackScreen.tsx @@ -245,7 +245,6 @@ const MainStackScreen: React.FC = ({route}) => { Date: Wed, 9 Jun 2021 09:24:00 +0900 Subject: Create separate pill component --- src/components/notifications/NotificationPill.tsx | 202 ++++++++++++++++++++ src/components/notifications/index.ts | 1 + src/routes/tabs/NavigationBar.tsx | 221 +--------------------- src/utils/common.ts | 1 + 4 files changed, 211 insertions(+), 214 deletions(-) create mode 100644 src/components/notifications/NotificationPill.tsx (limited to 'src/routes') 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 = ({ + showIcon, +}) => { + const [iconStart, setIconStart] = useState([0, -100]); + const [tipStart, setTipStart] = useState([0, -100]); + const [notificationSets, setNotificationSets] = useState({}); + const [timeCount, setTimeCount] = useState(false); + const [timeOut, setTimeOut] = useState(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 && ( + + + {notificationSets.CMT && ( + <> + + + {numberWithCommas(notificationSets.CMT)} + + + )} + {notificationSets.FR_REQ && ( + <> + + + {numberWithCommas(notificationSets.FR_REQ)} + + + )} + {notificationSets.P_VIEW && ( + <> + + + {numberWithCommas(notificationSets.P_VIEW)} + + + )} + {notificationSets.MOM_TAG && ( + <> + + + {numberWithCommas(notificationSets.MOM_TAG)} + + + )} + + + + )} + + ); +}; + +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, + }, +}); diff --git a/src/components/notifications/index.ts b/src/components/notifications/index.ts index 733b56f1..077c26a4 100644 --- a/src/components/notifications/index.ts +++ b/src/components/notifications/index.ts @@ -1,2 +1,3 @@ export {default as Notification} from './Notification'; export {InviteFriendsPrompt} from './NotificationPrompts'; +export {NotificationPill} from './NotificationPill'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index e962c8da..c3a42739 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -1,26 +1,14 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import React, {Fragment, useEffect, useState, useRef} from 'react'; -import {Image, StyleSheet, Text, View} from 'react-native'; -import LinearGradient from 'react-native-linear-gradient'; +import React, {Fragment, useEffect, useState} from 'react'; import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import { - getNotificationsUnreadCount, - setNotificationsReadDate, -} from '../../services'; +import {setNotificationsReadDate} from '../../services'; import {ScreenType} from '../../types'; -import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; +import {haveUnreadNotifications} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; -import { - NOTIFICATION_ICON_GRADIENT, - CHIN_HEIGHT, - NAV_BAR_HEIGHT, -} from '../../constants'; -import {normalize} from 'react-native-elements'; -import {numberWithCommas} from '../../utils'; -import PillIcon4 from '../../assets/images/Group 479.svg'; +import {NotificationPill} from '../../components/notifications'; const Tabs = createBottomTabNavigator(); @@ -32,17 +20,8 @@ const NavigationBar: React.FC = () => { const {notifications: {notifications} = NO_NOTIFICATIONS} = useSelector( (state: RootState) => state, ); + // Triggered if user clicks on Notifications page to close the pill const [showIcon, setShowIcon] = useState(true); - const [iconStart, setIconStart] = useState([0, -100]); - const [tipStart, setTipStart] = useState([0, -100]); - const [notificationSets, setNotificationSets] = useState({}); - const [timeCount, setTimeCount] = useState(false); - const [timeOut, setTimeOut] = useState(false); - const iconRef = useRef(null); - const tipRef = useRef(null); - const pillTip = require('../../assets/images/purple-tip.png'); - - const navBarPos = 20; const [unreadNotificationsPresent, setUnreadNotificationsPresent] = useState(false); @@ -58,132 +37,9 @@ const NavigationBar: React.FC = () => { determine(); }, [notifications]); - // 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 && ( - - - {notificationSets.CMT && ( - <> - - - {numberWithCommas(notificationSets.CMT)} - - - )} - {notificationSets.FR_REQ && ( - <> - - - {numberWithCommas(notificationSets.FR_REQ)} - - - )} - {notificationSets.P_VIEW && ( - <> - - - {numberWithCommas(notificationSets.P_VIEW)} - - - )} - {notificationSets.MOM_TAG && ( - <> - - - {numberWithCommas(notificationSets.MOM_TAG)} - - - )} - - - - )} + ({ tabBarIcon: ({focused}) => { @@ -233,23 +89,11 @@ const NavigationBar: React.FC = () => { name="SuggestedPeople" component={MainStackScreen} initialParams={{screenType: ScreenType.SuggestedPeople}} - // Added these to as a way to close pill when on - // notification page - listeners={{ - tabPress: (_) => { - setShowIcon(true); - }, - }} /> { - setShowIcon(true); - }, - }} /> { initialParams={{screenType: ScreenType.Notifications}} listeners={{ tabPress: (_) => { + // Closes the pill once this screen has been opened setShowIcon(false); // Updates backend's date of reading notifications setNotificationsReadDate(); @@ -267,67 +112,15 @@ const NavigationBar: React.FC = () => { name="Chat" component={MainStackScreen} initialParams={{screenType: ScreenType.Chat}} - listeners={{ - tabPress: (_) => { - setShowIcon(true); - }, - }} /> { - setShowIcon(true); - }, - }} /> ); }; -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, - }, -}); - export default NavigationBar; diff --git a/src/utils/common.ts b/src/utils/common.ts index 049dae90..cb0bd62d 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -198,6 +198,7 @@ export const validateImageLink = async (url: string | undefined) => { }); }; +// Documentation: https://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript export const numberWithCommas = (digits: number) => { return digits.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); }; -- cgit v1.2.3-70-g09d2 From ba55d9a29aae0fea3c5a7e4cb0cc9140c7d0fe31 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Wed, 9 Jun 2021 16:09:49 -0700 Subject: Update stack params for caption screen --- src/routes/main/MainStackNavigator.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/routes') diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx index d22c1874..8fce5e2f 100644 --- a/src/routes/main/MainStackNavigator.tsx +++ b/src/routes/main/MainStackNavigator.tsx @@ -37,14 +37,14 @@ export type MainStackParams = { screenType: ScreenType; }; CaptionScreen: { - title: string; - image: Image; + title?: string; + image?: Image; screenType: ScreenType; selectedTags?: MomentTagType[]; + moment?: MomentType; }; TagFriendsScreen: { - image: Image; - screenType: ScreenType; + imagePath: string; selectedTags?: MomentTagType[]; }; TagSelectionScreen: { -- cgit v1.2.3-70-g09d2