Skip to content

Commit 75650ce

Browse files
authored
fix: Trigger delete animation after delete API success
1 parent 487152f commit 75650ce

File tree

9 files changed

+60
-42
lines changed

9 files changed

+60
-42
lines changed

README.md

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ type Theme = {
8989
};
9090

9191
type ThemeProps = {
92-
notificationIcon?: {
93-
size?: number,
94-
},
9592
colors?: {
9693
primaryColor?: string,
9794
textColor?: string,
@@ -113,7 +110,6 @@ type ThemeProps = {
113110
background?: string,
114111
titleColor?: string,
115112
headerActionColor?: string,
116-
borderColor?: string,
117113
},
118114
windowContainer?: {
119115
background?: string,
@@ -152,7 +148,7 @@ Please note that the badgeStyle, window shadow and border props are only applica
152148
titleFontWeight?:TextStyle["fontWeight"],
153149
titleSize?: number,
154150
titlePadding?: number,
155-
borderWidth?: string;
151+
borderWidth?: string,
156152
},
157153
windowContainer?: {
158154
padding?: number,
@@ -177,29 +173,29 @@ Please note that the badgeStyle, window shadow and border props are only applica
177173
badgeStyle?: {
178174
size?: number,
179175
textSize?: number,
180-
top?: number;
176+
top?: number,
181177
right?: number
182178
},
183179
deleteIcon?:{
184180
size?: number
185-
}
186-
dateIcon?:{
181+
},
182+
timerIcon?:{
187183
size?: number
188-
}
184+
},
189185
clearAllIcon?:{
190186
size?: number
191-
}
187+
},
192188
}
193189
```
194190

195191
#### CardProps
196192

197193
```js
198194
type CardProps = {
199-
hideDelete?: boolean;
195+
hideDelete?: boolean,
200196
hideAvatar?: boolean,
201197
disableAutoMarkAsRead?: boolean,
202-
deleteIcon?: JSX.Element;
198+
deleteIcon?: JSX.Element,
203199
onAvatarClick?: () => void,
204200
};
205201
```
@@ -208,7 +204,7 @@ Please note that the badgeStyle, window shadow and border props are only applica
208204

209205
```js
210206
type InboxHeaderProps = {
211-
title?: string;
207+
title?: string,
212208
hideHeader?: boolean,
213209
hideClearAll?: boolean,
214210
customHeader?: JSX.Element | null,

src/components/Card.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { CSSProperties } from "react";
2-
import React, { type FC } from "react";
2+
import React, { type FC, useState } from "react";
33

44
import CloseIcon from "./CloseIcon";
55
import TimerIcon from "./TimerIcon";
@@ -8,6 +8,7 @@ import defaultAvatarLight from "../assets/light/defaultAvatarLight.png";
88
import type { NotificationCardProps } from "../types";
99
import { generateElapsedTimeText } from "../utils/commonUtils";
1010
import "../styles/card.css";
11+
import { events, eventTypes } from "../utils/constants";
1112
import useSiren from "../utils/sirenHook";
1213

1314
/**
@@ -48,28 +49,37 @@ const Card: FC<NotificationCardProps> = ({
4849
styles,
4950
darkMode,
5051
onCardClick,
51-
deleteById,
52+
deleteNotificationById,
5253
}) => {
53-
const { id, createdAt, message, isRead } = notification;
54+
const { createdAt, message, isRead } = notification;
5455
const { avatar, header, subHeader, body } = message;
5556
const { hideAvatar, hideDelete, disableAutoMarkAsRead, deleteIcon = null, onAvatarClick } = cardProps ?? {};
5657
const {
5758
markAsReadById
5859
} = useSiren();
5960

60-
const onDelete = (event: React.MouseEvent) => {
61-
const cardElement = event.currentTarget.closest(
62-
".siren-sdk-card-common-container"
63-
);
61+
const [deleteAnimationStyle, setDeleteAnimationStyle] = useState('');
6462

65-
cardElement?.classList.add("siren-sdk-delete-animation");
66-
setTimeout(() => {
67-
deleteById(id);
68-
}, 200);
63+
const onDelete = async (event: React.MouseEvent): Promise<void> => {
6964

7065
event.stopPropagation();
66+
67+
const isSuccess = await deleteNotificationById(notification.id, false);
68+
69+
if (isSuccess) {
70+
71+
setDeleteAnimationStyle("siren-sdk-delete-animation");
72+
73+
const payload = { id: notification.id, action: eventTypes.DELETE_ITEM };
74+
75+
setTimeout(() => {
76+
PubSub.publish(events.NOTIFICATION_LIST_EVENT, JSON.stringify(payload));
77+
}, 200)
78+
79+
}
7180
};
7281

82+
7383
const defaultAvatar = darkMode ? defaultAvatarDark : defaultAvatarLight;
7484
const cardContainerStyle: CSSProperties = isRead
7585
? {
@@ -99,7 +109,7 @@ const Card: FC<NotificationCardProps> = ({
99109
hideAvatar
100110
? "siren-sdk-hide-avatar-card-container"
101111
: "siren-sdk-card-container"
102-
} siren-sdk-card-common-container`}
112+
} siren-sdk-card-common-container ${deleteAnimationStyle}`}
103113
onClick={handleNotificationCardClick}
104114
aria-label={`siren-notification-card-${notification.id}`}
105115
data-testid={`card-${notification.id}`}

src/components/SirenNotificationIcon.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useSirenContext } from "./SirenProvider";
55
import "../styles/sirenNotificationIcon.css";
66
import type { SirenNotificationButtonProps } from "../types";
77
import { Constants } from "../utils";
8-
import { BadgeType, EventType } from "../utils/constants";
8+
import { BadgeType, EventType, MAX_UNVIEWED_COUNT_SHOWN } from "../utils/constants";
99

1010
const { eventTypes, events } = Constants;
1111

@@ -92,7 +92,7 @@ const SirenNotificationIcon: FC<SirenNotificationButtonProps> = ({
9292
};
9393

9494
const renderCount = useCallback(
95-
() => (unviewedCount > 99 ? "99+" : unviewedCount),
95+
() => (unviewedCount > MAX_UNVIEWED_COUNT_SHOWN ? `${MAX_UNVIEWED_COUNT_SHOWN}+` : unviewedCount),
9696
[unviewedCount]
9797
);
9898

src/components/SirenPanel.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,16 @@ const SirenPanel: FC<SirenPanelProps> = ({
117117
return () => {
118118
cleanUp();
119119
setNotifications([]);
120-
!hideBadge && restartNotificationCountFetch();
121120
handleMarkNotificationsAsViewed(new Date().toISOString());
122121
};
123122
}, [hideBadge, siren]);
124123

124+
useEffect(() => {
125+
return(() => {
126+
!hideBadge && restartNotificationCountFetch();
127+
})
128+
}, [hideBadge])
129+
125130
useEffect(() => {
126131
if (eventListenerData) {
127132
const updatedNotifications: NotificationDataType[] = updateNotifications(
@@ -270,14 +275,20 @@ const SirenPanel: FC<SirenPanelProps> = ({
270275
};
271276

272277
const deleteNotificationById = useCallback(
273-
async (id: string) => {
278+
async (id: string, shouldUpdateList: boolean) => {
279+
let isSuccess = false;
280+
274281
try {
275-
const response = await deleteById(id);
282+
const response = await deleteById(id, shouldUpdateList);
276283

284+
if (response?.data) isSuccess = true;
277285
response && triggerOnError(response);
278286
} catch (er) {
287+
isSuccess = false;
279288
// handle error if needed
280289
}
290+
291+
return isSuccess;
281292
},
282293
[deleteById, triggerOnError]
283294
);
@@ -328,7 +339,7 @@ const SirenPanel: FC<SirenPanelProps> = ({
328339
notification={item}
329340
cardProps={cardProps}
330341
onCardClick={onCardClick}
331-
deleteById={deleteNotificationById}
342+
deleteNotificationById={deleteNotificationById}
332343
styles={styles}
333344
key={item.id}
334345
darkMode={darkMode}

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export type NotificationCardProps = {
6161
cardProps: SirenInboxProps["cardProps"];
6262
onCardClick: SirenInboxProps["onCardClick"];
6363
styles: SirenStyleProps;
64-
deleteById: (id: string) => void;
64+
deleteNotificationById: (id: string, shouldUpdateList: boolean) => Promise <boolean>;
6565
darkMode: boolean;
6666
};
6767

src/utils/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export const AUTHENTICATION_FAILED = 'AUTHENTICATION_FAILED';
105105
export const TOKEN_VERIFICATION_PENDING ='TOKEN_VERIFICATION_PENDING';
106106
export const MAXIMUM_RETRY_COUNT = 3;
107107
export const MAXIMUM_ITEMS_PER_FETCH = 50;
108+
export const MAX_UNVIEWED_COUNT_SHOWN = 99;
108109

109110
export const errorMap = {
110111
SIREN_OBJECT_NOT_FOUND: {

src/utils/sirenHook.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ const useSiren = () => {
4343

4444
return { error: errorMap.SIREN_OBJECT_NOT_FOUND };
4545
};
46-
const deleteById = async (id: string) => {
46+
const deleteById = async (id: string, shouldUpdateList: boolean = true) => {
4747
if (siren)
4848
if (id?.length > 0) {
4949
const response = await siren?.deleteById(id);
5050

51-
if (response && response.data) {
51+
if (response?.data && shouldUpdateList) {
5252
const payload = { id, action: eventTypes.DELETE_ITEM };
5353

5454
PubSub.publish(

tests/components/__snapshots__/card.spec.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ exports[`matches snapshot 1`] = `
44
<DocumentFragment>
55
<div
66
aria-label="siren-notification-card-1"
7-
class="siren-sdk-card-container siren-sdk-card-common-container"
7+
class="siren-sdk-card-container siren-sdk-card-common-container "
88
data-testid="card-1"
99
style="background-color: rgb(46, 45, 48); padding: 12px; border-bottom: 0.5px solid; border-color: #344054; border-left: 4px solid #FA9874;"
1010
>

tests/components/card.spec.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ test("matches snapshot", () => {
3636
const { asFragment } = render(
3737
<Card
3838
notification={mockNotification}
39-
deleteById={mockDeleteNotificationById}
39+
deleteNotificationById={mockDeleteNotificationById}
4040
onCardClick={mockOnNotificationCardClick}
4141
cardProps={{}}
4242
styles={style}
@@ -50,7 +50,7 @@ test("renders notification card with basic content", () => {
5050
const screen = render(
5151
<Card
5252
notification={mockNotification}
53-
deleteById={mockDeleteNotificationById}
53+
deleteNotificationById={mockDeleteNotificationById}
5454
onCardClick={mockOnNotificationCardClick}
5555
cardProps={{}}
5656
styles={style}
@@ -68,7 +68,7 @@ test("triggers delete notification callback on delete button click", () => {
6868
const screen = render(
6969
<Card
7070
notification={mockNotification}
71-
deleteById={mockDeleteNotificationById}
71+
deleteNotificationById={mockDeleteNotificationById}
7272
onCardClick={mockOnNotificationCardClick}
7373
cardProps={{}}
7474
styles={style}
@@ -84,7 +84,7 @@ test("triggers delete notification callback on delete button click", () => {
8484
jest.advanceTimersByTime(200);
8585
});
8686

87-
expect(mockDeleteNotificationById).toHaveBeenCalledWith("1");
87+
expect(mockDeleteNotificationById).toHaveBeenCalledWith("1", false);
8888

8989
jest.useRealTimers();
9090
});
@@ -93,7 +93,7 @@ test("triggers notification card click callback on card click", () => {
9393
const screen = render(
9494
<Card
9595
notification={mockNotification}
96-
deleteById={mockDeleteNotificationById}
96+
deleteNotificationById={mockDeleteNotificationById}
9797
onCardClick={mockOnNotificationCardClick}
9898
cardProps={{ hideAvatar: true }}
9999
styles={style}
@@ -111,7 +111,7 @@ test("renders header, subheader, and body", () => {
111111
const screen = render(
112112
<Card
113113
notification={mockNotification}
114-
deleteById={mockDeleteNotificationById}
114+
deleteNotificationById={mockDeleteNotificationById}
115115
onCardClick={mockOnNotificationCardClick}
116116
cardProps={{}}
117117
styles={style}
@@ -132,7 +132,7 @@ test("does not render avatar if hideAvatar is true", () => {
132132
const screen = render(
133133
<Card
134134
notification={mockNotification}
135-
deleteById={mockDeleteNotificationById}
135+
deleteNotificationById={mockDeleteNotificationById}
136136
onCardClick={mockOnNotificationCardClick}
137137
cardProps={{ hideAvatar: true }}
138138
styles={style}

0 commit comments

Comments
 (0)