-
+
- {notification?.courseName}
+ {courseName}
{intl.formatMessage(messages.fullStop)}
- {timeago.format(notification?.createdAt, 'time-locale')}
+ {timeago.format(createdAt, 'time-locale')}
- {!notification.lastRead && (
-
-
+
);
};
NotificationRowItem.propTypes = {
- notification: PropTypes.object.isRequired,
+ id: PropTypes.string.isRequired,
+ type: PropTypes.string.isRequired,
+ contentUrl: PropTypes.string.isRequired,
+ content: PropTypes.node.isRequired,
+ courseName: PropTypes.string.isRequired,
+ createdAt: PropTypes.string.isRequired,
+ lastRead: PropTypes.string.isRequired,
};
export default React.memo(NotificationRowItem);
diff --git a/src/Notifications/NotificationSections.jsx b/src/Notifications/NotificationSections.jsx
index b40f873..d9aa446 100644
--- a/src/Notifications/NotificationSections.jsx
+++ b/src/Notifications/NotificationSections.jsx
@@ -1,83 +1,78 @@
-/* eslint-disable jsx-a11y/click-events-have-key-events */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-import React, { useCallback } from 'react';
+import React, { useCallback, useMemo } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useSelector, useDispatch } from 'react-redux';
import { Button } from '@edx/paragon';
-import PropTypes from 'prop-types';
+import isEmpty from 'lodash/isEmpty';
import { messages } from './messages';
import NotificationRowItem from './NotificationRowItem';
import {
- getSelectedAppNotificationIds, getSelectedAppName, getNotificationsByIds, getPaginationData,
+ getSelectedAppNotificationIds,
+ getSelectedAppName,
+ getNotificationsByIds,
+ getPaginationData,
} from './data/selectors';
import { splitNotificationsByTime } from './utils';
import { markAllNotificationsAsRead } from './data/thunks';
-const NotificationSections = ({ handleLoadMoreNotification }) => {
+const NotificationSections = () => {
const intl = useIntl();
+ const dispatch = useDispatch();
const selectedAppName = useSelector(getSelectedAppName());
const notificationIds = useSelector(getSelectedAppNotificationIds(selectedAppName));
const notifications = useSelector(getNotificationsByIds(notificationIds));
const paginationData = useSelector(getPaginationData());
- const { today = [], earlier = [] } = splitNotificationsByTime(notifications);
- const dispatch = useDispatch();
+ const { today = [], earlier = [] } = useMemo(
+ () => splitNotificationsByTime(notifications),
+ [notifications],
+ );
const handleMarkAllAsRead = useCallback(() => {
dispatch(markAllNotificationsAsRead(selectedAppName));
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [selectedAppName]);
+ }, [dispatch, selectedAppName]);
+
+ const renderNotificationSection = (section, items) => {
+ if (isEmpty(items)) { return null; }
+
+ return (
+
+
+
+ {section === 'today' && intl.formatMessage(messages.notificationTodayHeading)}
+ {section === 'earlier' && intl.formatMessage(messages.notificationEarlierHeading)}
+
+ {notifications?.length > 0 && (section === 'earlier' ? today.length === 0 : true) && (
+
+ {intl.formatMessage(messages.notificationMarkAsRead)}
+
+ )}
+
+ {items.map((notification) => (
+
+ ))}
+
+ );
+ };
return (
- notifications && (
-
- {today.length > 0 && (
- <>
-
- { intl.formatMessage(messages.notificationTodayHeading)}
-
- {today.length + earlier.length > 0 && (
-
- {intl.formatMessage(messages.notificationMarkAsRead)}
-
- )}
- >
- )}
-
- {today.map(
- (notification) =>
,
- )}
-
-
-
- {earlier.length > 0
- && intl.formatMessage(messages.notificationEarlierHeading)}
-
- {today.length + earlier.length > 0 && today.length === 0 && (
-
- {intl.formatMessage(messages.notificationMarkAsRead)}
-
- )}
-
- {earlier.map(
- (notification) =>
,
- )}
+ {renderNotificationSection('today', today)}
+ {renderNotificationSection('earlier', earlier)}
{paginationData.currentPage < paginationData.numPages && (
-
+
)}
- )
);
};
-NotificationSections.propTypes = {
- handleLoadMoreNotification: PropTypes.func.isRequired,
-};
-
export default React.memo(NotificationSections);
diff --git a/src/Notifications/NotificationTabs.jsx b/src/Notifications/NotificationTabs.jsx
index 9540be3..8468f5f 100644
--- a/src/Notifications/NotificationTabs.jsx
+++ b/src/Notifications/NotificationTabs.jsx
@@ -8,53 +8,37 @@ import { getNotificationTabsCount, getSelectedAppName, getNotificationTabs } fro
import { fetchNotificationList, markNotificationsAsSeen } from './data/thunks';
const NotificationTabs = () => {
+ const dispatch = useDispatch();
+ const [page, setPage] = useState(1);
+ const selectedAppName = useSelector(getSelectedAppName());
const notificationUnseenCounts = useSelector(getNotificationTabsCount());
const notificationTabs = useSelector(getNotificationTabs());
- const selectedAppName = useSelector(getSelectedAppName());
- const [activeTab, setActiveTab] = useState(selectedAppName);
- const [page, setPage] = useState(1);
- const dispatch = useDispatch();
useEffect(() => {
- dispatch(fetchNotificationList({ appName: activeTab, page, pageSize: 10 }));
+ dispatch(fetchNotificationList({ appName: selectedAppName, page, pageSize: 10 }));
if (selectedAppName) { dispatch(markNotificationsAsSeen(selectedAppName)); }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [activeTab, page, selectedAppName]);
+ }, [dispatch, page, selectedAppName]);
- const handleActiveTab = useCallback((tab) => {
- setActiveTab(tab);
- setPage(1);
+ const handleActiveTab = useCallback((appName) => {
+ // dispatch(setSelectedAppName(appName));
}, []);
- const handleLoadMoreNotification = useCallback(() => {
- setPage(page + 1);
- }, [page]);
-
- const tabArray = useMemo(() => notificationTabs?.map((option) => (
+ const tabArray = useMemo(() => notificationTabs?.map((appName) => (
- {option === selectedAppName && (
-
- )}
+ {appName === selectedAppName && ()}
- )), [notificationUnseenCounts, handleLoadMoreNotification, selectedAppName, notificationTabs]);
-
- // This code is used to replace More... text to More to match the UI
- const buttons = document.getElementsByClassName('dropdown-toggle');
- for (let i = 0; i < buttons.length; i++) {
- buttons[i].firstChild.nodeValue = 'More';
- }
+ )), [notificationUnseenCounts, selectedAppName, notificationTabs]);
return (
diff --git a/src/Notifications/Notifications.jsx b/src/Notifications/Notifications.jsx
index 2a68268..5ebb9ef 100644
--- a/src/Notifications/Notifications.jsx
+++ b/src/Notifications/Notifications.jsx
@@ -25,25 +25,22 @@ const Notifications = () => {
const isOnMediumScreen = useIsOnMediumScreen();
const isOnLargeScreen = useIsOnLargeScreen();
- console.log('isOnMediumScreen', isOnMediumScreen);
- console.log('isOnLargeScreen', isOnLargeScreen);
-
- const handleNotificationTray = useCallback((value) => {
- setShowNotificationTray(value);
- if (!value) { dispatch(resetNotificationState()); }
+ const hideNotificationTray = useCallback(() => {
+ setShowNotificationTray(prevState => !prevState);
}, []);
const handleClickOutside = useCallback((event) => {
- if (popoverRef.current?.contains(event.target) !== true && buttonRef.current?.contains(event.target) !== true) {
+ if (!popoverRef.current?.contains(event.target) && !buttonRef.current?.contains(event.target)) {
setShowNotificationTray(false);
- dispatch(resetNotificationState());
}
}, []);
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
+
return () => {
document.removeEventListener('mousedown', handleClickOutside);
+ dispatch(resetNotificationState());
};
}, []);
@@ -80,20 +77,22 @@ const Notifications = () => {
{ handleNotificationTray(!showNotificationTray); }}
+ onClick={hideNotificationTray}
src={NotificationsNone}
iconAs={Icon}
variant="light"
iconClassNames="text-primary-500"
className="ml-4 mr-1 my-3 notification-button"
/>
-
- { notificationCounts?.count > 0 && notificationCounts?.count}
-
+ {notificationCounts?.count > 0 && (
+
+ {notificationCounts.count}
+
+ )}
);
diff --git a/src/Notifications/data/notifications.json b/src/Notifications/data/notifications.json
index 581c786..87e4eb6 100644
--- a/src/Notifications/data/notifications.json
+++ b/src/Notifications/data/notifications.json
@@ -68,7 +68,7 @@
"content_url": "",
"last_read": null,
"last_seen": null,
- "created_at": "2023-06-01T00:36:11.979531Z"
+ "created_at": "2023-06-05T00:36:11.979531Z"
},
{
"id": 8,
diff --git a/src/index.scss b/src/index.scss
index e8c2f9c..d9a607e 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -125,34 +125,37 @@ $white: #fff;
.font-size-18{
font-size: 18px !important;
}
+
.font-size-12{
font-size: 12px;
}
+
.font-size-9{
font-size: 9px;
}
+
.line-height-24{
line-height: 24px;
}
+
.line-height-20{
line-height: 20px;
}
+
.icon-size-20{
width: 20px !important;
height: 20px !important;
}
+
.cursor-pointer{
cursor: pointer;
}
-#popover-positioned-bottom{
- max-height: calc(100% - 68px);
- min-height: 1220px;
- min-width: 549px;
-}
+
.notification-button{
width: 36px;
height: 36px;
}
+
.notification-badge{
position: absolute;
margin-top: 18px;
@@ -160,7 +163,14 @@ $white: #fff;
border: 2px solid #FFFFFF;
}
-.notification-tray-container{
+.notification-tray-container {
+ max-height: calc(100% - 68px);
+ min-height: 1220px;
+
+ .popover {
+
+ }
+
&.medium-screen {
min-width: 24.313rem;
}