-
Notifications
You must be signed in to change notification settings - Fork 1
/
BrazeCards.ts
158 lines (137 loc) · 4.62 KB
/
BrazeCards.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import type appboy from '@braze/web-sdk-core';
import { ErrorHandler, Extras, CardSlotName, CardSlotNames } from './types';
interface BrazeCardsInterface {
getCardsForProfileBadge: () => BrazeCard[];
}
class BrazeCard {
id: string;
slotName: CardSlotName;
private card: appboy.Card;
private appboy: typeof appboy;
private errorHandler: ErrorHandler;
constructor(
id: string,
slotName: CardSlotName,
card: appboy.Card,
appboyInstance: typeof appboy,
errorHandler: ErrorHandler,
) {
this.id = id;
this.slotName = slotName;
this.card = card;
this.appboy = appboyInstance;
this.errorHandler = errorHandler;
}
logImpression(): void {
try {
const result = this.appboy.logCardImpressions([this.card], true);
if (!result) {
this.errorHandler(
new Error('Failed to log card impression event'),
'BrazeCard.logImpressions',
);
}
} catch (error: unknown) {
if (error instanceof Error) {
this.errorHandler(error, 'BrazeCard.logImpressions');
}
}
}
logCardClick(): void {
try {
const result = this.appboy.logCardClick(this.card, true);
if (!result) {
this.errorHandler(
new Error('Failed to log card click event'),
'BrazeCard.logCardClick',
);
}
} catch (error: unknown) {
if (error instanceof Error) {
this.errorHandler(error, 'BrazeCard.logCardClick');
}
}
}
logCardDismissal(): void {
try {
const result = this.appboy.logCardDismissal(this.card);
if (!result) {
this.errorHandler(
new Error('Failed to log card dismiss event'),
'BrazeCard.logCardDismiss',
);
}
} catch (error: unknown) {
if (error instanceof Error) {
this.errorHandler(error, 'BrazeCard.logCardDismiss');
}
}
}
/**
* Returns the card's key/value pairs.
*
* We know this can't be empty because there must have been at least a `slotName`
* field present to be able to generate the card.
*/
get extras(): Extras {
const data = this.card.extras;
// since empty extras is impossible, let's add this case to eliminate undefined from the type
if (data === undefined) {
return {};
} else {
return data;
}
}
get expiry(): Date | undefined {
const expiryDate = this.card.expiresAt;
if (expiryDate === null) {
return undefined;
} else {
return expiryDate;
}
}
}
class BrazeCards implements BrazeCardsInterface {
appboy: typeof appboy;
errorHandler: ErrorHandler;
constructor(appboyInstance: typeof appboy, errorHandler: ErrorHandler) {
this.appboy = appboyInstance;
this.errorHandler = errorHandler;
}
getCardsForProfileBadge(): BrazeCard[] {
return this.getCardsForSlot(CardSlotNames.ProfileBadge);
}
private getCardsForSlot(targetSlotName: CardSlotName): BrazeCard[] {
const cachedCards = this.appboy.getCachedContentCards().cards.flatMap((appboyCard) => {
const { extras } = appboyCard;
if (extras && extras.slotName && extras.slotName === targetSlotName) {
if (appboyCard.id === undefined) {
this.errorHandler(
new Error('appboy card had no ID'),
'BrazeCards.getCardsForSlot',
);
return [];
} else {
return [
new BrazeCard(
appboyCard.id,
targetSlotName,
appboyCard,
this.appboy,
this.errorHandler,
),
];
}
} else {
// TODO: Consider whether this an error state, or something we're happy to ignore
// Will there be other content cards in users' feeds that we should ignore?
return [];
}
});
return cachedCards;
}
get lastUpdated(): Date | null {
return this.appboy.getCachedContentCards().lastUpdated;
}
}
export { BrazeCard, BrazeCards, BrazeCardsInterface };