Skip to content

Commit ba1ece2

Browse files
committed
feat: implement notification list component
1 parent e81d2fa commit ba1ece2

21 files changed

+506
-139
lines changed
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 9 additions & 0 deletions
Loading
Lines changed: 9 additions & 0 deletions
Loading
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import '../../../../../packages/core/src/ui/styles/theme.scss';
2+
@import '../../../../../packages/common/src/ui/styles/theme.scss';
3+
4+
.icon {
5+
width: size_unit(10.5);
6+
height: size_unit(10.5);
7+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
import { Flex, Text } from '@input-output-hk/lace-ui-toolkit';
3+
import { useTranslation } from 'react-i18next';
4+
import styles from './EmptyState.module.scss';
5+
import SmileyFaceIcon from '../../assets/icons/smiley-face.component.svg';
6+
7+
export const EmptyState = (): React.ReactElement => {
8+
const { t } = useTranslation();
9+
10+
return (
11+
<Flex flexDirection="column" gap="$20" alignItems="center" justifyContent="center" data-testid="empty-state">
12+
<SmileyFaceIcon className={styles.icon} />
13+
<Flex alignItems="center" flexDirection="column" gap="$0">
14+
<Text.Body.Large>{t('notificationsCenter.emptyState.title')}</Text.Body.Large>
15+
<Text.Body.Small color="secondary">{t('notificationsCenter.emptyState.description')}</Text.Body.Small>
16+
</Flex>
17+
</Flex>
18+
);
19+
};

apps/browser-extension-wallet/src/components/NotificationsCenter/NotificationListItem.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,32 @@ import TrashOutlineComponent from '../../assets/icons/browser-view/trash-icon.co
55
import { useTranslation } from 'react-i18next';
66
import classnames from 'classnames';
77

8+
export type LaceMessage = {
9+
id: string;
10+
topic: string;
11+
title: string;
12+
body: string;
13+
format: string;
14+
};
15+
16+
export type LaceNotification = {
17+
message: LaceMessage;
18+
read?: boolean;
19+
};
20+
821
export interface NotificationListItemProps {
22+
id: string;
923
title: string;
1024
isRead?: boolean;
1125
popupView?: boolean;
1226
publisher: string;
13-
onRemove?: () => void;
27+
onRemove?: (id: string) => void;
1428
onClick: () => void;
1529
withBorder?: boolean;
1630
}
1731

1832
export const NotificationListItem = ({
33+
id,
1934
title,
2035
isRead = false,
2136
popupView = false,
@@ -28,7 +43,7 @@ export const NotificationListItem = ({
2843

2944
const handleRemove = (e: React.MouseEvent<HTMLButtonElement>) => {
3045
e.stopPropagation();
31-
onRemove();
46+
onRemove?.(id);
3247
};
3348

3449
const PublisherTextComponent = popupView ? Text.Label : Text.Body.Small;
@@ -55,6 +70,7 @@ export const NotificationListItem = ({
5570
onClick={onClick}
5671
className={classnames(styles.container, withBorder && styles.withBorder)}
5772
p="$20"
73+
w="$fill"
5874
>
5975
<Flex className={styles.content} justifyContent="center" alignItems="flex-start" flexDirection="column" gap="$8">
6076
<Flex alignItems="center" gap="$4" className={styles.copy}>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* eslint-disable unicorn/no-useless-undefined */
2+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types, promise/catch-or-return, sonarjs/cognitive-complexity, no-magic-numbers, unicorn/no-null */
3+
import React, { useState } from 'react';
4+
import { ContentLayout } from '@src/components/Layout';
5+
import { useTranslation } from 'react-i18next';
6+
import { WarningModal } from '@src/views/browser-view/components';
7+
import { useNotificationsCenter } from '@hooks/useNotificationsCenter';
8+
import { NotificationsList } from './NotificationsList';
9+
import { EmptyState } from './EmptyState';
10+
import { Box, Flex } from '@input-output-hk/lace-ui-toolkit';
11+
import { NavigationButton } from '@lace/common';
12+
import { useHistory } from 'react-router';
13+
import { SectionTitle } from '@components/Layout/SectionTitle';
14+
15+
export const NotificationsCenter = (): React.ReactElement => {
16+
const { t } = useTranslation();
17+
const [isRemoveNotificationModalVisible, setIsRemoveNotificationModalVisible] = useState(false);
18+
const { notifications, loadMore, remove, unreadNotifications, isLoading } = useNotificationsCenter();
19+
const [notificationIdToRemove, setNotificationIdToRemove] = useState<string | undefined>();
20+
const history = useHistory();
21+
22+
const onShowRemoveNotificationModal = (id: string) => {
23+
setNotificationIdToRemove(id);
24+
setIsRemoveNotificationModalVisible(true);
25+
};
26+
27+
const onHideRemoveNotificationModal = () => {
28+
setNotificationIdToRemove(undefined);
29+
setIsRemoveNotificationModalVisible(false);
30+
};
31+
32+
const isInitialLoad = typeof notifications === 'undefined';
33+
34+
return (
35+
<ContentLayout
36+
title={
37+
<SectionTitle
38+
isPopup
39+
title={
40+
<Flex alignItems="center" gap="$8">
41+
<NavigationButton icon="arrow" onClick={() => history.goBack()} />
42+
{t('notificationsCenter.title')}
43+
</Flex>
44+
}
45+
sideText={`(${unreadNotifications})`}
46+
data-testid="notifications-center-title"
47+
/>
48+
}
49+
isLoading={isInitialLoad}
50+
>
51+
<div>
52+
{notifications?.length > 0 ? (
53+
<NotificationsList
54+
isLoading={isLoading}
55+
hasMore
56+
loadMore={loadMore}
57+
notifications={notifications}
58+
scrollableTarget="contentLayout"
59+
dataLength={notifications.length}
60+
onRemove={onShowRemoveNotificationModal}
61+
popupView
62+
/>
63+
) : (
64+
<Box mt="$96">
65+
<EmptyState />
66+
</Box>
67+
)}
68+
</div>
69+
<WarningModal
70+
visible={isRemoveNotificationModalVisible}
71+
header={t('notificationsCenter.removeNotification')}
72+
content={t('notificationsCenter.removeNotification.description')}
73+
onCancel={onHideRemoveNotificationModal}
74+
cancelLabel={t('notificationsCenter.removeNotification.cancel')}
75+
confirmLabel={t('notificationsCenter.removeNotification.confirm')}
76+
onConfirm={() => {
77+
remove(notificationIdToRemove);
78+
onHideRemoveNotificationModal();
79+
}}
80+
isPopupView
81+
/>
82+
</ContentLayout>
83+
);
84+
};

apps/browser-extension-wallet/src/components/NotificationsCenter/NotificationsAllClear.tsx

Lines changed: 0 additions & 20 deletions
This file was deleted.

apps/browser-extension-wallet/src/components/NotificationsCenter/NotificationsBell.module.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@
2525
padding: size_unit(1) size_unit(2.75) !important;
2626
position: relative;
2727
}
28+
29+
.icon {
30+
width: size_unit(2);
31+
height: size_unit(2);
32+
}

apps/browser-extension-wallet/src/components/NotificationsCenter/NotificationsBell.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import { Button } from '@lace/common';
44

55
import styles from './NotificationsBell.module.scss';
66

7-
import NotificationBellIcon from '@lace/core/src/ui/assets/icons/notifications-bell.component.svg';
7+
import NotificationBellIcon from '../../assets/icons/notifications-bell.component.svg';
88

9-
// eslint-disable-next-line no-magic-numbers
10-
const formatNotificationCount = (count: number) => (count < 10 ? count.toString() : '9+');
9+
const MAX_NOTIFICATION_COUNT = 9;
10+
const formatNotificationCount = (count: number) =>
11+
count < MAX_NOTIFICATION_COUNT ? count.toString() : `${MAX_NOTIFICATION_COUNT}+`;
1112

1213
export interface NotificationsBellProps {
1314
onClick: () => void;
@@ -16,7 +17,7 @@ export interface NotificationsBellProps {
1617

1718
export const NotificationsBell = ({ onClick, unreadNotifications }: NotificationsBellProps): React.ReactElement => (
1819
<Button className={styles.btn} block color="gradient" data-testid="notifications-bell" onClick={onClick}>
19-
<NotificationBellIcon />
20+
<NotificationBellIcon className={styles.icon} />
2021
{unreadNotifications > 0 && <span className={styles.badge}>{formatNotificationCount(unreadNotifications)}</span>}
2122
</Button>
2223
);

0 commit comments

Comments
 (0)