|
1 | 1 | // TypeScript |
2 | 2 | import { useState, useEffect } from 'react' |
3 | 3 | import { useTranslation } from 'react-i18next' |
4 | | -import { Button, CloseButton } from '@iqss/dataverse-design-system' |
| 4 | +import { Button, CloseButton, Stack } from '@iqss/dataverse-design-system' |
5 | 5 | import { getTranslatedNotification } from '@/sections/account/notifications-section/NotificationsHelper' |
6 | 6 | import { needsUpdateStore } from '@/notifications/domain/hooks/needsUpdateStore' |
7 | 7 | import styles from './NotificationsSection.module.scss' |
@@ -32,12 +32,13 @@ export const NotificationsSection = ({ notificationRepository }: NotificationsSe |
32 | 32 | const unreadIds = notifications |
33 | 33 | .filter((n) => !n.displayAsRead && !readIds.includes(n.id)) |
34 | 34 | .map((n) => n.id) |
35 | | - |
| 35 | + console.log('in useEffect, unreadIds:', unreadIds) |
36 | 36 | if (unreadIds.length > 0) { |
37 | 37 | const timer = setTimeout(() => { |
38 | 38 | void (async () => { |
39 | 39 | await markAsRead(unreadIds) |
40 | 40 | setReadIds((prev) => [...prev, ...unreadIds]) |
| 41 | + console.log('calling refetch after marking as read') |
41 | 42 | await refetch() |
42 | 43 | needsUpdateStore.setNeedsUpdate(true) |
43 | 44 | })() |
@@ -68,63 +69,68 @@ export const NotificationsSection = ({ notificationRepository }: NotificationsSe |
68 | 69 | const pageSize = Math.max(1, paginationInfo?.pageSize ?? (notifications.length || 1)) |
69 | 70 | const start = notifications.length === 0 ? 0 : (page - 1) * pageSize + 1 |
70 | 71 | const end = notifications.length === 0 ? 0 : Math.min(start + notifications.length - 1, total) |
| 72 | + const totalPages = Math.ceil(total / pageSize) |
71 | 73 | const clearAllKey = |
72 | 74 | total > pageSize ? 'notifications.clearAllOnThisPage' : 'notifications.clearAll' |
73 | 75 |
|
74 | 76 | return ( |
75 | 77 | <section> |
76 | | - <div className="d-flex align-items-center gap-2 mb-2"> |
77 | | - {notifications.length > 0 && ( |
78 | | - <Button |
79 | | - size="sm" |
80 | | - variant="secondary" |
81 | | - aria-label={t('notifications.clearAll')} |
82 | | - onClick={handleClearAll} |
83 | | - disabled={isLoading}> |
84 | | - {t(clearAllKey)} |
85 | | - </Button> |
86 | | - )} |
| 78 | + <Stack gap={3} style={{ width: '100%' }}> |
| 79 | + <Stack |
| 80 | + direction="horizontal" |
| 81 | + gap={2} |
| 82 | + style={{ width: '100%', justifyContent: 'space-between', alignItems: 'center' }}> |
| 83 | + {totalPages >= 2 ? ( |
| 84 | + <div>{t('notifications.displayingNotifications', { start, end, total })}</div> |
| 85 | + ) : ( |
| 86 | + <div /> /* placeholder to keep spacing when there's no range text */ |
| 87 | + )} |
87 | 88 |
|
88 | | - <div className="ms-auto d-flex align-items-center gap-2"></div> |
89 | | - </div> |
| 89 | + {notifications.length > 0 && ( |
| 90 | + <Button |
| 91 | + size="sm" |
| 92 | + variant="secondary" |
| 93 | + aria-label={t(clearAllKey)} |
| 94 | + onClick={handleClearAll} |
| 95 | + disabled={isLoading}> |
| 96 | + {t(clearAllKey)} |
| 97 | + </Button> |
| 98 | + )} |
| 99 | + </Stack> |
90 | 100 |
|
91 | | - {notifications.length > 0 ? ( |
92 | | - <div className="d-flex flex-column gap-2"> |
93 | | - <div |
94 | | - className={ |
95 | | - styles['range-info'] |
96 | | - }>{`Displaying ${start}-${end} of ${total} Notifications`}</div> |
97 | | - |
98 | | - {notifications.map((notification) => { |
99 | | - const isRead = notification.displayAsRead || readIds.includes(notification.id) |
100 | | - return ( |
101 | | - <div |
102 | | - className={`${styles['notification-item']} ${ |
103 | | - isRead ? styles['read'] : styles['unread'] |
104 | | - }`} |
105 | | - key={notification.id}> |
106 | | - <div> |
107 | | - {getTranslatedNotification(notification, t)} |
108 | | - <span className={styles['timestamp']}>{notification.sentTimestamp}</span> |
| 101 | + {notifications.length > 0 ? ( |
| 102 | + <div className="d-flex flex-column gap-2"> |
| 103 | + {notifications.map((notification) => { |
| 104 | + const isRead = notification.displayAsRead || readIds.includes(notification.id) |
| 105 | + return ( |
| 106 | + <div |
| 107 | + className={`${styles['notification-item']} ${ |
| 108 | + isRead ? styles['read'] : styles['unread'] |
| 109 | + }`} |
| 110 | + key={notification.id}> |
| 111 | + <div> |
| 112 | + {getTranslatedNotification(notification, t)} |
| 113 | + <span className={styles['timestamp']}>{notification.sentTimestamp}</span> |
| 114 | + </div> |
| 115 | + <CloseButton |
| 116 | + onClick={async () => { |
| 117 | + await handleDelete(notification.id) |
| 118 | + }} |
| 119 | + aria-label={t('notifications.dismiss')} |
| 120 | + data-testid={`dismiss-notification-${notification.id}`} |
| 121 | + /> |
109 | 122 | </div> |
110 | | - <CloseButton |
111 | | - onClick={async () => { |
112 | | - await handleDelete(notification.id) |
113 | | - }} |
114 | | - aria-label={t('notifications.dismiss')} |
115 | | - data-testid={`dismiss-notification-${notification.id}`} |
116 | | - /> |
117 | | - </div> |
118 | | - ) |
119 | | - })} |
120 | | - <PaginationControls |
121 | | - initialPaginationInfo={paginationInfo} |
122 | | - onPaginationInfoChange={setPaginationInfo} |
123 | | - /> |
124 | | - </div> |
125 | | - ) : ( |
126 | | - <div>{t('notifications.noNotifications')}</div> |
127 | | - )} |
| 123 | + ) |
| 124 | + })} |
| 125 | + <PaginationControls |
| 126 | + initialPaginationInfo={paginationInfo} |
| 127 | + onPaginationInfoChange={setPaginationInfo} |
| 128 | + /> |
| 129 | + </div> |
| 130 | + ) : ( |
| 131 | + <div>{t('notifications.noNotifications')}</div> |
| 132 | + )} |
| 133 | + </Stack> |
128 | 134 | </section> |
129 | 135 | ) |
130 | 136 | } |
|
0 commit comments