aboutsummaryrefslogtreecommitdiff
path: root/src/screens/main/NotificationsScreen.tsx
diff options
context:
space:
mode:
authorIvan Chen <ivan@thetaggid.com>2020-12-29 20:21:24 -0500
committerGitHub <noreply@github.com>2020-12-29 20:21:24 -0500
commitbd2f89805d0bb1c2f1d08fe8d91099aa4f109d35 (patch)
treeac7219e034a0c4035096c6df8dbe6b92446b5111 /src/screens/main/NotificationsScreen.tsx
parentec478d4981c726856485b49b49ac33b0d9e6a903 (diff)
[TMA-461] Notifications Screen (#151)
* renamed ProfileStack to MainStack, created initial notifications data type * cleaned up code * added notifications to redux * finished sectioned list * updated types to make more sense * finished sectioned notifications by date * updated notification type and tested mock backend integration * finished read or unread logic * minor changes * another minor fix * finished integration * moved stuff * added ability to navigate to user profile Co-authored-by: Husam Salhab <47015061+hsalhab@users.noreply.github.com>
Diffstat (limited to 'src/screens/main/NotificationsScreen.tsx')
-rw-r--r--src/screens/main/NotificationsScreen.tsx167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx
new file mode 100644
index 00000000..2343215f
--- /dev/null
+++ b/src/screens/main/NotificationsScreen.tsx
@@ -0,0 +1,167 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import moment from 'moment';
+import React, {useCallback, useEffect, useState} from 'react';
+import {
+ RefreshControl,
+ SectionList,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import {SafeAreaView} from 'react-native-safe-area-context';
+import {useDispatch, useSelector} from 'react-redux';
+import {Notification} from '../../components/notifications';
+import {loadUserNotifications} from '../../store/actions';
+import {RootState} from '../../store/rootReducer';
+import {NotificationType, ScreenType} from '../../types';
+import {getDateAge, SCREEN_HEIGHT} from '../../utils';
+
+const NotificationsScreen: React.FC = () => {
+ const [refreshing, setRefreshing] = useState(false);
+ // used for figuring out which ones are unread
+ const [lastViewed, setLastViewed] = useState<moment.Moment | undefined>(
+ undefined,
+ );
+ const {notifications} = useSelector(
+ (state: RootState) => state.notifications,
+ );
+ const [sectionedNotifications, setSectionedNotifications] = useState<
+ {title: 'Today' | 'Yesterday' | 'This Week'; data: NotificationType[]}[]
+ >([]);
+
+ const dispatch = useDispatch();
+
+ const onRefresh = useCallback(() => {
+ const refrestState = async () => {
+ dispatch(loadUserNotifications());
+ };
+ setRefreshing(true);
+ refrestState().then(() => {
+ setRefreshing(false);
+ });
+ }, [dispatch]);
+
+ // handles storing and fetching the "previously viewed" information
+ useEffect(() => {
+ const getAndUpdateLastViewed = async () => {
+ const key = 'notificationLastViewed';
+ const previousLastViewed = await AsyncStorage.getItem(key);
+ setLastViewed(
+ previousLastViewed == null
+ ? moment.unix(0)
+ : moment(previousLastViewed),
+ );
+ await AsyncStorage.setItem(key, moment().toString());
+ };
+ getAndUpdateLastViewed();
+ }, [notifications]);
+
+ // handles sectioning notifications to "date age"
+ // mark notifications as read or unread
+ useEffect(() => {
+ const sortedNotifications = (notifications ?? [])
+ .slice()
+ .sort((a, b) => (a.timestamp < b.timestamp ? 1 : -1));
+ let todays = [];
+ let yesterdays = [];
+ let thisWeeks = [];
+ for (const n of sortedNotifications) {
+ const notificationDate = moment(n.timestamp);
+ const dateAge = getDateAge(notificationDate);
+ if (dateAge === 'unknown') {
+ continue;
+ }
+ const unread = lastViewed ? lastViewed.diff(notificationDate) < 0 : false;
+ const newN = {...n, unread};
+ switch (dateAge) {
+ case 'today':
+ todays.push(newN);
+ continue;
+ case 'yesterday':
+ yesterdays.push(newN);
+ continue;
+ case 'thisWeek':
+ thisWeeks.push(newN);
+ continue;
+ default:
+ continue;
+ }
+ }
+ setSectionedNotifications([
+ {
+ title: 'Today',
+ data: todays,
+ },
+ {
+ title: 'Yesterday',
+ data: yesterdays,
+ },
+ {
+ title: 'This Week',
+ data: thisWeeks,
+ },
+ ]);
+ }, [lastViewed, notifications]);
+
+ const renderNotification = ({item}: {item: NotificationType}) => (
+ <Notification item={item} screenType={ScreenType.Notifications} />
+ );
+
+ const renderSectionHeader = ({section: {title}}) => (
+ <View style={styles.sectionHeaderContainer}>
+ <Text style={styles.sectionHeader}>{title}</Text>
+ </View>
+ );
+
+ return (
+ <SafeAreaView>
+ <View style={styles.header}>
+ <Text style={styles.headerText}>Notifications</Text>
+ <View style={styles.underline} />
+ </View>
+ <SectionList
+ contentContainerStyle={styles.container}
+ sections={sectionedNotifications}
+ keyExtractor={(item, index) => index.toString()}
+ renderItem={renderNotification}
+ renderSectionHeader={renderSectionHeader}
+ refreshControl={
+ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
+ }
+ />
+ </SafeAreaView>
+ );
+};
+
+const styles = StyleSheet.create({
+ header: {
+ marginLeft: '5%',
+ marginTop: '5%',
+ alignSelf: 'flex-start',
+ flexDirection: 'column',
+ },
+ headerText: {
+ fontWeight: 'bold',
+ fontSize: 16,
+ },
+ underline: {
+ borderWidth: 2,
+ borderColor: '#8F01FF',
+ },
+ container: {
+ paddingBottom: '20%',
+ minHeight: (SCREEN_HEIGHT * 8) / 10,
+ },
+ sectionHeaderContainer: {
+ width: '100%',
+ backgroundColor: '#f3f2f2',
+ },
+ sectionHeader: {
+ marginLeft: '5%',
+ marginTop: '5%',
+ marginBottom: '2%',
+ fontSize: 16,
+ },
+});
+
+export default NotificationsScreen;