@kompasid/lit-web-components 0.8.7 → 0.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/empty-state-notification.png +0 -0
- package/demo/index.html +24 -7
- package/dist/src/components/kompasid-grace-period/KompasGracePeriod.d.ts +1 -0
- package/dist/src/components/kompasid-grace-period/KompasGracePeriod.js +20 -6
- package/dist/src/components/kompasid-grace-period/KompasGracePeriod.js.map +1 -1
- package/dist/src/components/kompasid-header-notification/KompasHeaderNotification.d.ts +35 -0
- package/dist/src/components/kompasid-header-notification/KompasHeaderNotification.js +482 -0
- package/dist/src/components/kompasid-header-notification/KompasHeaderNotification.js.map +1 -0
- package/dist/src/components/kompasid-header-notification/types.d.ts +35 -0
- package/dist/src/components/kompasid-header-notification/types.js +2 -0
- package/dist/src/components/kompasid-header-notification/types.js.map +1 -0
- package/dist/src/components/kompasid-header-notification/utils.d.ts +21 -0
- package/dist/src/components/kompasid-header-notification/utils.js +43 -0
- package/dist/src/components/kompasid-header-notification/utils.js.map +1 -0
- package/dist/src/components/kompasid-paywall-body/KompasPaywallBody.js +2 -1
- package/dist/src/components/kompasid-paywall-body/KompasPaywallBody.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/components/kompasid-grace-period/KompasGracePeriod.ts +24 -6
- package/src/components/kompasid-header-notification/KompasHeaderNotification.ts +548 -0
- package/src/components/kompasid-header-notification/types.ts +39 -0
- package/src/components/kompasid-header-notification/utils.ts +86 -0
- package/src/components/kompasid-paywall-body/KompasPaywallBody.ts +2 -1
- package/src/index.ts +1 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { LitElement, html, css } from 'lit';
|
|
3
|
+
import { format, isToday, formatDistanceStrict, subDays } from 'date-fns';
|
|
4
|
+
import { id } from 'date-fns/locale/id';
|
|
5
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
6
|
+
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
7
|
+
import { getFontAwesomeIcon } from '../../utils/fontawesome-setup.js';
|
|
8
|
+
import { TWStyles } from '../../../tailwind/tailwind.js';
|
|
9
|
+
import { customFetch } from './utils.js';
|
|
10
|
+
let KompasHeaderNotification = class KompasHeaderNotification extends LitElement {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.isShowDropdown = false;
|
|
14
|
+
this.selectedTab = 'Info';
|
|
15
|
+
this.notificationInfoData = {};
|
|
16
|
+
this.notificationContentData = [];
|
|
17
|
+
this.isDataLoaded = false;
|
|
18
|
+
this.accessToken = ''; // prod || dev
|
|
19
|
+
this.refreshToken = ''; // prod || dev
|
|
20
|
+
this.handleClick = (value) => {
|
|
21
|
+
this.selectedTab = value;
|
|
22
|
+
};
|
|
23
|
+
this.redirectTo = async (notifId, link) => {
|
|
24
|
+
const res = await this.notifRead(notifId);
|
|
25
|
+
if (res.status === 200) {
|
|
26
|
+
this.notificationInfoData = {
|
|
27
|
+
...this.notificationInfoData,
|
|
28
|
+
notificationList: this.notificationInfoData.notificationList.map(notifItem => ({
|
|
29
|
+
...notifItem,
|
|
30
|
+
isRead: notifItem.notificationId === notifId ? true : notifItem.isRead,
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (link) {
|
|
35
|
+
const url = new URL(decodeURIComponent(link));
|
|
36
|
+
window.open(url, '_blank');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
this.handleClickOutside = this.handleClickOutside.bind(this);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Function to format date
|
|
43
|
+
*/
|
|
44
|
+
formatDate(date) {
|
|
45
|
+
// Check if the provided date is today
|
|
46
|
+
let result;
|
|
47
|
+
if (isToday(date)) {
|
|
48
|
+
// Return time difference if it's today (e.g., "7 hours ago")
|
|
49
|
+
result = `${formatDistanceStrict(date, new Date(), { locale: id })} lalu`;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Return formatted date (e.g., "12 Sep 2024, 09:00")
|
|
53
|
+
result = format(date, 'dd MMM yyyy, HH:mm', { locale: id });
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
async connectedCallback() {
|
|
58
|
+
super.connectedCallback();
|
|
59
|
+
this.isShowDropdown = false;
|
|
60
|
+
if (this.accessToken && this.refreshToken)
|
|
61
|
+
await this.loadData();
|
|
62
|
+
document.addEventListener('click', this.handleClickOutside);
|
|
63
|
+
}
|
|
64
|
+
async disconnectedCallback() {
|
|
65
|
+
super.disconnectedCallback();
|
|
66
|
+
document.removeEventListener('click', this.handleClickOutside);
|
|
67
|
+
}
|
|
68
|
+
async apiFetch(url, options) {
|
|
69
|
+
const response = await customFetch(url, this.refreshToken, this.accessToken, { ...options });
|
|
70
|
+
return response;
|
|
71
|
+
}
|
|
72
|
+
async getNotifRubrik() {
|
|
73
|
+
const req = this.apiFetch('https://cds.kompas.cloud/api/v1/article/pilihanku', {
|
|
74
|
+
method: 'GET',
|
|
75
|
+
headers: {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
return req;
|
|
80
|
+
}
|
|
81
|
+
async getNotifList() {
|
|
82
|
+
const req = await this.apiFetch('https://api.kompas.cloud/account/api/v1/users/notification', {
|
|
83
|
+
method: 'GET',
|
|
84
|
+
headers: {
|
|
85
|
+
'Content-Type': 'application/json',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
return req;
|
|
89
|
+
}
|
|
90
|
+
async getEpaperData() {
|
|
91
|
+
const formatDate = 'yyyy/MM/dd';
|
|
92
|
+
const startDate = format(subDays(new Date(), 1), formatDate);
|
|
93
|
+
const endDate = format(new Date(), formatDate).toString();
|
|
94
|
+
const req = await this.apiFetch(`https://apiepaper.kompas.cloud/products?startDate=${startDate}&endDate=${endDate}&sort=desc`, {
|
|
95
|
+
method: 'GET',
|
|
96
|
+
headers: {
|
|
97
|
+
'Content-Type': 'application/json',
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
return req;
|
|
101
|
+
}
|
|
102
|
+
async notifRead(notifId) {
|
|
103
|
+
const req = await this.apiFetch('https://api.kompas.cloud/account/api/v1/users/notification/read', {
|
|
104
|
+
headers: {
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
},
|
|
107
|
+
method: 'PUT',
|
|
108
|
+
body: JSON.stringify({
|
|
109
|
+
notificationId: notifId,
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
return req;
|
|
113
|
+
}
|
|
114
|
+
async loadData() {
|
|
115
|
+
const apiCalls = [
|
|
116
|
+
this.getNotifList(),
|
|
117
|
+
this.getNotifRubrik(),
|
|
118
|
+
this.getEpaperData(),
|
|
119
|
+
];
|
|
120
|
+
this.isDataLoaded = false;
|
|
121
|
+
Promise.all(apiCalls)
|
|
122
|
+
.then(responses => Promise.all(responses.map(response => response.json())))
|
|
123
|
+
.then(values => {
|
|
124
|
+
this.notificationInfoData = values[0].data;
|
|
125
|
+
const rubrikData = values[1].result;
|
|
126
|
+
const ePaperData = values[2].data[0];
|
|
127
|
+
const { publishDate, description, thumbnail, title, url } = ePaperData;
|
|
128
|
+
const data = {
|
|
129
|
+
title,
|
|
130
|
+
category: [{ name: 'ePaper', slug: 'epaper' }],
|
|
131
|
+
publishedDateGmt: format(new Date(publishDate), 'yyyy-MM-dd HH:mm:ss'),
|
|
132
|
+
permalink: url,
|
|
133
|
+
thumbnails: {
|
|
134
|
+
sizes: { thumbnailSquareMedium: { permalink: thumbnail } },
|
|
135
|
+
},
|
|
136
|
+
excerpt: description,
|
|
137
|
+
};
|
|
138
|
+
this.notificationContentData = [data, ...rubrikData];
|
|
139
|
+
this.notificationContentData.sort((a, b) => new Date(b.publishedDateGmt).getTime() -
|
|
140
|
+
new Date(a.publishedDateGmt).getTime());
|
|
141
|
+
this.isDataLoaded = true;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
toggleDropdown() {
|
|
145
|
+
this.isShowDropdown = !this.isShowDropdown;
|
|
146
|
+
}
|
|
147
|
+
notificationIcon() {
|
|
148
|
+
const notificationIndicator = () => {
|
|
149
|
+
if (!this.notificationInfoData.notificationCount)
|
|
150
|
+
return html ``;
|
|
151
|
+
return html `<div
|
|
152
|
+
class="header-account--notification-indicator animate-ping"
|
|
153
|
+
></div>`;
|
|
154
|
+
};
|
|
155
|
+
return html `
|
|
156
|
+
<button
|
|
157
|
+
@click=${this.toggleDropdown}
|
|
158
|
+
class="cursor-pointer relative flex items-center"
|
|
159
|
+
>
|
|
160
|
+
${notificationIndicator()}
|
|
161
|
+
<div class="flex flex-row items-center self-center">
|
|
162
|
+
<div class="text-white cursor-pointer mt-0.5">
|
|
163
|
+
${unsafeSVG(getFontAwesomeIcon('fas', 'bell', 21, 21))}
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</button>
|
|
167
|
+
`;
|
|
168
|
+
}
|
|
169
|
+
handleClickOutside(event) {
|
|
170
|
+
var _a;
|
|
171
|
+
if (!this.isShowDropdown)
|
|
172
|
+
return;
|
|
173
|
+
const popup = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('headerNotification');
|
|
174
|
+
const ev = event.composedPath();
|
|
175
|
+
if (this.isShowDropdown && popup && !(ev === null || ev === void 0 ? void 0 : ev.includes(popup))) {
|
|
176
|
+
this.isShowDropdown = false; // Close the popup
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Notification Info
|
|
180
|
+
notificationInfoSection() {
|
|
181
|
+
const { notificationList } = this.notificationInfoData;
|
|
182
|
+
// Empty state
|
|
183
|
+
if (!notificationList.length)
|
|
184
|
+
return html `
|
|
185
|
+
<div class="text-center px-4 pt-6 pb-32">
|
|
186
|
+
<img
|
|
187
|
+
src="../../assets/empty-state-notification.png"
|
|
188
|
+
alt="empty-state-notification"
|
|
189
|
+
class="w-auto mx-auto"
|
|
190
|
+
/>
|
|
191
|
+
<p class="font-bold text-center text-lg py-2">Belum Ada Notifikasi</p>
|
|
192
|
+
<p class="px-2">
|
|
193
|
+
Kami akan memberitahukan Anda ketika ada informasi dan pemberitahuan
|
|
194
|
+
terbaru.
|
|
195
|
+
</p>
|
|
196
|
+
</div>
|
|
197
|
+
`;
|
|
198
|
+
const notificationInfoListTemplate = (item) => {
|
|
199
|
+
const imgUrl = item.label === 'Akun'
|
|
200
|
+
? `https://cdn-www.kompas.id/assets/notifikasi-akun.svg`
|
|
201
|
+
: `https://cdn-www.kompas.id/assets/langganan-anda-telah-berakhir.svg`;
|
|
202
|
+
return html `<div class="w-3/4 pr-1">
|
|
203
|
+
<div class="flex items-center mb-1 text-xs">
|
|
204
|
+
<span class="text-green-500 bg-green-100 rounded-sm p-1 px-2">
|
|
205
|
+
${item.label}
|
|
206
|
+
</span>
|
|
207
|
+
<span class="text-grey-400 ml-2"
|
|
208
|
+
>${this.formatDate(item.time)}</span
|
|
209
|
+
>
|
|
210
|
+
</div>
|
|
211
|
+
<div>
|
|
212
|
+
<p class="text-sm font-bold">${item.title}</p>
|
|
213
|
+
<p class="text-sm">${item.description}</p>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
<div class="w-1/4">
|
|
217
|
+
<img src="${imgUrl}" alt="${item.label}-alt" class="w-14 h-14" />
|
|
218
|
+
</div>`;
|
|
219
|
+
};
|
|
220
|
+
return html `<div class="h-[300px] overflow-y-scroll">
|
|
221
|
+
${notificationList.map(item => html `<button
|
|
222
|
+
class="flex w-full text-left items-start p-4 cursor-pointer justify-between ${!item.isRead
|
|
223
|
+
? 'bg-blue-100'
|
|
224
|
+
: ''}"
|
|
225
|
+
@click=${() => this.redirectTo(item.notificationId, item.link)}
|
|
226
|
+
>
|
|
227
|
+
${notificationInfoListTemplate(item)}
|
|
228
|
+
</button> `)}
|
|
229
|
+
</div>
|
|
230
|
+
<!-- Footer Link -->
|
|
231
|
+
<div class="px-4 py-4 text-center">
|
|
232
|
+
<a href="#" @click="${() => this.redirectToNotification('info')}" class="text-base font-bold text-blue-500">
|
|
233
|
+
Lihat Selengkapnya</a
|
|
234
|
+
>
|
|
235
|
+
</div>
|
|
236
|
+
</div>`;
|
|
237
|
+
}
|
|
238
|
+
redirectToNotification(tab) {
|
|
239
|
+
window.open(`https://account.kompas.id/manage-account/notification/${tab}`, '_blank');
|
|
240
|
+
}
|
|
241
|
+
// Notification Content
|
|
242
|
+
notificationContentSection() {
|
|
243
|
+
// Empty state
|
|
244
|
+
if (!this.notificationContentData.length) {
|
|
245
|
+
return html `
|
|
246
|
+
<div class="text-center px-4 pt-6 pb-32">
|
|
247
|
+
<img
|
|
248
|
+
src="../../assets/empty-state-notification.png"
|
|
249
|
+
alt="empty-state-notification"
|
|
250
|
+
class="w-auto mx-auto"
|
|
251
|
+
/>
|
|
252
|
+
<p class="font-bold text-center text-lg py-2">Belum Ada Notifikasi</p>
|
|
253
|
+
<p class="px-2">
|
|
254
|
+
Kami akan memberitahukan Anda ketika ada informasi dan pemberitahuan
|
|
255
|
+
terbaru.
|
|
256
|
+
</p>
|
|
257
|
+
</div>
|
|
258
|
+
`;
|
|
259
|
+
}
|
|
260
|
+
const notificationContentListTemplate = (item) => html `<div
|
|
261
|
+
class="w-3/4 pr-1 "
|
|
262
|
+
>
|
|
263
|
+
<div class="flex items-center mb-1 text-xs">
|
|
264
|
+
<span class="text-green-500 bg-green-100 rounded-sm p-1 px-2">
|
|
265
|
+
${item.category[0].name}
|
|
266
|
+
</span>
|
|
267
|
+
<span class="text-grey-400 ml-2">
|
|
268
|
+
${this.formatDate(item.publishedDateGmt)}</span
|
|
269
|
+
>
|
|
270
|
+
</div>
|
|
271
|
+
<p class="font-bold text-base text-customTextColor py-1">
|
|
272
|
+
${item.title}
|
|
273
|
+
</p>
|
|
274
|
+
</div>
|
|
275
|
+
<div class="w-1/4">
|
|
276
|
+
<img
|
|
277
|
+
src="${item.thumbnails.sizes.thumbnailSquareMedium.permalink}"
|
|
278
|
+
alt="content-img-alt"
|
|
279
|
+
class="w-14 h-14 object-cover"
|
|
280
|
+
/>
|
|
281
|
+
</div>`;
|
|
282
|
+
return html `<div class="h-[300px] overflow-y-scroll">
|
|
283
|
+
${this.notificationContentData.map(item => html `<button
|
|
284
|
+
class="flex w-full text-left items-start p-4 cursor-pointer justify-between ${!item.isRead
|
|
285
|
+
? 'bg-blue-100'
|
|
286
|
+
: ''}"
|
|
287
|
+
@click=${() => window.open(item.permalink, '_blank')}
|
|
288
|
+
>
|
|
289
|
+
${notificationContentListTemplate(item)}
|
|
290
|
+
</button> `)}
|
|
291
|
+
</div>
|
|
292
|
+
<!-- Footer Link -->
|
|
293
|
+
<div class="px-4 py-4 text-center">
|
|
294
|
+
<a href="#" @click="${() => this.redirectToNotification('konten')}" class="text-base font-bold text-blue-500">
|
|
295
|
+
Lihat Selengkapnya</a
|
|
296
|
+
>
|
|
297
|
+
</div>
|
|
298
|
+
</div>`;
|
|
299
|
+
}
|
|
300
|
+
notificationPopup() {
|
|
301
|
+
const tab = ['Info', 'Konten'];
|
|
302
|
+
return html `
|
|
303
|
+
<div
|
|
304
|
+
id="notificationPopup"
|
|
305
|
+
class="header-notificaion-dropdown rounded-lg shadow-lg z-50 mt-2 ${this
|
|
306
|
+
.isShowDropdown
|
|
307
|
+
? 'active'
|
|
308
|
+
: ''}"
|
|
309
|
+
>
|
|
310
|
+
<div class="sticky">
|
|
311
|
+
<div class="flex justify-center py-2 border-b border-grey-300">
|
|
312
|
+
<span class="font-bold text-base">Notifikasi</span>
|
|
313
|
+
</div>
|
|
314
|
+
<!-- Tabs for Info and Content -->
|
|
315
|
+
<div class="flex justify-between">
|
|
316
|
+
${tab.map(item => html `
|
|
317
|
+
<button
|
|
318
|
+
class="focus:outline-none py-2 w-1/2 ${this.selectedTab ===
|
|
319
|
+
item && 'link-active'}"
|
|
320
|
+
@click=${() => this.handleClick(item)}
|
|
321
|
+
>
|
|
322
|
+
${item}
|
|
323
|
+
</button>
|
|
324
|
+
`)}
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
<!-- Notification Content -->
|
|
329
|
+
${this.selectedTab === 'Info'
|
|
330
|
+
? this.notificationInfoSection()
|
|
331
|
+
: this.notificationContentSection()}
|
|
332
|
+
</div>
|
|
333
|
+
`;
|
|
334
|
+
}
|
|
335
|
+
render() {
|
|
336
|
+
return html `<div id="headerNotification" class="relative">
|
|
337
|
+
${this.isDataLoaded
|
|
338
|
+
? this.notificationIcon()
|
|
339
|
+
: html `<div class="text-white cursor-pointer mt-0.5 animate-spin">
|
|
340
|
+
${unsafeSVG(getFontAwesomeIcon('fa', 'circle-notch', 21, 21))}
|
|
341
|
+
</div>`}
|
|
342
|
+
${this.isShowDropdown ? this.notificationPopup() : ''}
|
|
343
|
+
</div>`;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
KompasHeaderNotification.styles = [
|
|
347
|
+
css `
|
|
348
|
+
:host {
|
|
349
|
+
font-family: 'PT Sans', sans-serif;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.header-account--notification-indicator {
|
|
353
|
+
position: absolute;
|
|
354
|
+
top: 0;
|
|
355
|
+
height: 0.5rem;
|
|
356
|
+
width: 0.5rem;
|
|
357
|
+
background-color: #ff7a00;
|
|
358
|
+
border-radius: 50%;
|
|
359
|
+
right: -0.403rem;
|
|
360
|
+
top: -0.281rem;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.header-notificaion-dropdown {
|
|
364
|
+
width: 20.5rem;
|
|
365
|
+
background-color: #ffffff;
|
|
366
|
+
font-family: 'PT Sans', sans-serif;
|
|
367
|
+
font-size: 0.875rem;
|
|
368
|
+
position: absolute;
|
|
369
|
+
right: -7.5vmax;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.w-14 {
|
|
373
|
+
width: 3.25rem;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.h-\\[300px\\] {
|
|
377
|
+
height: 300px;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.h-14 {
|
|
381
|
+
height: 3.25rem;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.bg-green-100 {
|
|
385
|
+
--tw-bg-opacity: 1;
|
|
386
|
+
background-color: rgb(238 252 210 / var(--tw-bg-opacity));
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.overflow-y-scroll {
|
|
390
|
+
overflow-y: scroll;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.link-active {
|
|
394
|
+
color: #0468cb;
|
|
395
|
+
border-color: #0468cb;
|
|
396
|
+
border-bottom-width: 3px;
|
|
397
|
+
background-color: transparent !important;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.animate-spin {
|
|
401
|
+
animation: spin 2s linear infinite;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@keyframes spin {
|
|
405
|
+
from {
|
|
406
|
+
transform: rotate(0deg);
|
|
407
|
+
}
|
|
408
|
+
to {
|
|
409
|
+
transform: rotate(360deg);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.object-cover {
|
|
414
|
+
object-fit: cover;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.z-index-max {
|
|
418
|
+
z-index: 99999;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/* Custom Scrollbar for header */
|
|
422
|
+
/* width */
|
|
423
|
+
::-webkit-scrollbar {
|
|
424
|
+
width: 4px;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Track */
|
|
428
|
+
::-webkit-scrollbar-track {
|
|
429
|
+
background: transparent;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* Handle */
|
|
433
|
+
::-webkit-scrollbar-thumb {
|
|
434
|
+
background: #0356a8;
|
|
435
|
+
border-radius: 100px;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/* Handle on hover */
|
|
439
|
+
::-webkit-scrollbar-thumb:hover {
|
|
440
|
+
background: #0356a8;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
@media (min-width: 1024px) {
|
|
444
|
+
.header-notificaion-dropdown {
|
|
445
|
+
right: -4vmax;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
@media (max-width: 360px) {
|
|
450
|
+
.header-notificaion-dropdown {
|
|
451
|
+
right: -10vmax;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
`,
|
|
455
|
+
TWStyles,
|
|
456
|
+
];
|
|
457
|
+
__decorate([
|
|
458
|
+
state()
|
|
459
|
+
], KompasHeaderNotification.prototype, "isShowDropdown", void 0);
|
|
460
|
+
__decorate([
|
|
461
|
+
state()
|
|
462
|
+
], KompasHeaderNotification.prototype, "selectedTab", void 0);
|
|
463
|
+
__decorate([
|
|
464
|
+
state()
|
|
465
|
+
], KompasHeaderNotification.prototype, "notificationInfoData", void 0);
|
|
466
|
+
__decorate([
|
|
467
|
+
state()
|
|
468
|
+
], KompasHeaderNotification.prototype, "notificationContentData", void 0);
|
|
469
|
+
__decorate([
|
|
470
|
+
state()
|
|
471
|
+
], KompasHeaderNotification.prototype, "isDataLoaded", void 0);
|
|
472
|
+
__decorate([
|
|
473
|
+
property({ type: String })
|
|
474
|
+
], KompasHeaderNotification.prototype, "accessToken", void 0);
|
|
475
|
+
__decorate([
|
|
476
|
+
property({ type: String })
|
|
477
|
+
], KompasHeaderNotification.prototype, "refreshToken", void 0);
|
|
478
|
+
KompasHeaderNotification = __decorate([
|
|
479
|
+
customElement('kompasid-header-notification')
|
|
480
|
+
], KompasHeaderNotification);
|
|
481
|
+
export { KompasHeaderNotification };
|
|
482
|
+
//# sourceMappingURL=KompasHeaderNotification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KompasHeaderNotification.js","sourceRoot":"","sources":["../../../../src/components/kompasid-header-notification/KompasHeaderNotification.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { format, isToday, formatDistanceStrict, subDays } from 'date-fns'\nimport { id } from 'date-fns/locale/id'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeSVG } from 'lit/directives/unsafe-svg.js'\nimport { getFontAwesomeIcon } from '../../utils/fontawesome-setup.js'\nimport { TWStyles } from '../../../tailwind/tailwind.js'\nimport {\n UserNotification,\n NotificationList,\n ApiResponse,\n ApiRubrikResponse,\n} from './types.js'\nimport { customFetch } from './utils.js'\n\n@customElement('kompasid-header-notification')\nexport class KompasHeaderNotification extends LitElement {\n static styles = [\n css`\n :host {\n font-family: 'PT Sans', sans-serif;\n }\n\n .header-account--notification-indicator {\n position: absolute;\n top: 0;\n height: 0.5rem;\n width: 0.5rem;\n background-color: #ff7a00;\n border-radius: 50%;\n right: -0.403rem;\n top: -0.281rem;\n }\n\n .header-notificaion-dropdown {\n width: 20.5rem;\n background-color: #ffffff;\n font-family: 'PT Sans', sans-serif;\n font-size: 0.875rem;\n position: absolute;\n right: -7.5vmax;\n }\n\n .w-14 {\n width: 3.25rem;\n }\n\n .h-\\\\[300px\\\\] {\n height: 300px;\n }\n\n .h-14 {\n height: 3.25rem;\n }\n\n .bg-green-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(238 252 210 / var(--tw-bg-opacity));\n }\n\n .overflow-y-scroll {\n overflow-y: scroll;\n }\n\n .link-active {\n color: #0468cb;\n border-color: #0468cb;\n border-bottom-width: 3px;\n background-color: transparent !important;\n }\n\n .animate-spin {\n animation: spin 2s linear infinite;\n }\n\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n\n .object-cover {\n object-fit: cover;\n }\n\n .z-index-max {\n z-index: 99999;\n }\n\n /* Custom Scrollbar for header */\n /* width */\n ::-webkit-scrollbar {\n width: 4px;\n }\n\n /* Track */\n ::-webkit-scrollbar-track {\n background: transparent;\n }\n\n /* Handle */\n ::-webkit-scrollbar-thumb {\n background: #0356a8;\n border-radius: 100px;\n }\n\n /* Handle on hover */\n ::-webkit-scrollbar-thumb:hover {\n background: #0356a8;\n }\n\n @media (min-width: 1024px) {\n .header-notificaion-dropdown {\n right: -4vmax;\n }\n }\n\n @media (max-width: 360px) {\n .header-notificaion-dropdown {\n right: -10vmax;\n }\n }\n `,\n TWStyles,\n ]\n\n @state() isShowDropdown: boolean = false\n @state() selectedTab: string = 'Info'\n @state() notificationInfoData: UserNotification = {} as UserNotification\n @state() notificationContentData: any[] = []\n @state() isDataLoaded: boolean = false\n\n @property({ type: String }) accessToken = '' // prod || dev\n @property({ type: String }) refreshToken = '' // prod || dev\n\n constructor() {\n super()\n this.handleClickOutside = this.handleClickOutside.bind(this)\n }\n\n /**\n * Function to format date\n */\n formatDate(date: string) {\n // Check if the provided date is today\n let result\n if (isToday(date)) {\n // Return time difference if it's today (e.g., \"7 hours ago\")\n result = `${formatDistanceStrict(date, new Date(), { locale: id })} lalu`\n } else {\n // Return formatted date (e.g., \"12 Sep 2024, 09:00\")\n result = format(date, 'dd MMM yyyy, HH:mm', { locale: id })\n }\n return result\n }\n\n override async connectedCallback() {\n super.connectedCallback()\n this.isShowDropdown = false\n\n if (this.accessToken && this.refreshToken) await this.loadData()\n document.addEventListener('click', this.handleClickOutside)\n }\n\n override async disconnectedCallback() {\n super.disconnectedCallback()\n document.removeEventListener('click', this.handleClickOutside)\n }\n\n private async apiFetch(url: string, options: any) {\n const response = await customFetch(\n url,\n this.refreshToken,\n this.accessToken,\n { ...options }\n )\n\n return response\n }\n\n private async getNotifRubrik() {\n const req = this.apiFetch(\n 'https://cds.kompas.cloud/api/v1/article/pilihanku',\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n return req\n }\n\n private async getNotifList() {\n const req = await this.apiFetch(\n 'https://api.kompas.cloud/account/api/v1/users/notification',\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n return req\n }\n\n private async getEpaperData() {\n const formatDate = 'yyyy/MM/dd'\n const startDate = format(subDays(new Date(), 1), formatDate)\n const endDate = format(new Date(), formatDate).toString()\n const req = await this.apiFetch(\n `https://apiepaper.kompas.cloud/products?startDate=${startDate}&endDate=${endDate}&sort=desc`,\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n\n return req\n }\n\n private async notifRead(notifId: string) {\n const req = await this.apiFetch(\n 'https://api.kompas.cloud/account/api/v1/users/notification/read',\n {\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'PUT',\n body: JSON.stringify({\n notificationId: notifId,\n }),\n }\n )\n return req\n }\n\n private async loadData() {\n const apiCalls = [\n this.getNotifList(),\n this.getNotifRubrik(),\n this.getEpaperData(),\n ]\n this.isDataLoaded = false\n\n Promise.all(apiCalls)\n .then(responses =>\n Promise.all(responses.map(response => response.json()))\n )\n .then(values => {\n this.notificationInfoData = (\n values[0] as ApiResponse<UserNotification>\n ).data\n const rubrikData = (values[1] as ApiRubrikResponse<any>).result\n const ePaperData = (values[2] as ApiResponse<any>).data[0]\n const { publishDate, description, thumbnail, title, url } = ePaperData\n\n const data = {\n title,\n category: [{ name: 'ePaper', slug: 'epaper' }],\n publishedDateGmt: format(\n new Date(publishDate),\n 'yyyy-MM-dd HH:mm:ss'\n ),\n permalink: url,\n thumbnails: {\n sizes: { thumbnailSquareMedium: { permalink: thumbnail } },\n },\n excerpt: description,\n }\n\n this.notificationContentData = [data, ...rubrikData]\n this.notificationContentData.sort(\n (a: any, b: any) =>\n new Date(b.publishedDateGmt).getTime() -\n new Date(a.publishedDateGmt).getTime()\n )\n\n this.isDataLoaded = true\n })\n }\n\n private toggleDropdown() {\n this.isShowDropdown = !this.isShowDropdown\n }\n\n private notificationIcon() {\n const notificationIndicator = () => {\n if (!this.notificationInfoData.notificationCount) return html``\n return html`<div\n class=\"header-account--notification-indicator animate-ping\"\n ></div>`\n }\n\n return html`\n <button\n @click=${this.toggleDropdown}\n class=\"cursor-pointer relative flex items-center\"\n >\n ${notificationIndicator()}\n <div class=\"flex flex-row items-center self-center\">\n <div class=\"text-white cursor-pointer mt-0.5\">\n ${unsafeSVG(getFontAwesomeIcon('fas', 'bell', 21, 21))}\n </div>\n </div>\n </button>\n `\n }\n\n private handleClick = (value: string) => {\n this.selectedTab = value\n }\n\n private redirectTo = async (notifId: string, link: string) => {\n const res = await this.notifRead(notifId)\n\n if (res.status === 200) {\n this.notificationInfoData = {\n ...this.notificationInfoData,\n notificationList: this.notificationInfoData.notificationList.map(\n notifItem => ({\n ...notifItem,\n isRead:\n notifItem.notificationId === notifId ? true : notifItem.isRead,\n })\n ),\n }\n }\n\n if (link) {\n const url = new URL(decodeURIComponent(link))\n\n window.open(url, '_blank')\n }\n }\n\n private handleClickOutside(event: Event) {\n if (!this.isShowDropdown) return\n\n const popup = this.shadowRoot?.getElementById('headerNotification')\n const ev = event.composedPath()\n if (this.isShowDropdown && popup && !ev?.includes(popup as HTMLElement)) {\n this.isShowDropdown = false // Close the popup\n }\n }\n\n // Notification Info\n private notificationInfoSection() {\n const { notificationList }: { notificationList: NotificationList[] } =\n this.notificationInfoData\n\n // Empty state\n if (!notificationList.length)\n return html`\n <div class=\"text-center px-4 pt-6 pb-32\">\n <img\n src=\"../../assets/empty-state-notification.png\"\n alt=\"empty-state-notification\"\n class=\"w-auto mx-auto\"\n />\n <p class=\"font-bold text-center text-lg py-2\">Belum Ada Notifikasi</p>\n <p class=\"px-2\">\n Kami akan memberitahukan Anda ketika ada informasi dan pemberitahuan\n terbaru.\n </p>\n </div>\n `\n\n const notificationInfoListTemplate = (item: NotificationList) => {\n const imgUrl =\n item.label === 'Akun'\n ? `https://cdn-www.kompas.id/assets/notifikasi-akun.svg`\n : `https://cdn-www.kompas.id/assets/langganan-anda-telah-berakhir.svg`\n\n return html`<div class=\"w-3/4 pr-1\">\n <div class=\"flex items-center mb-1 text-xs\">\n <span class=\"text-green-500 bg-green-100 rounded-sm p-1 px-2\">\n ${item.label}\n </span>\n <span class=\"text-grey-400 ml-2\"\n >${this.formatDate(item.time)}</span\n >\n </div>\n <div>\n <p class=\"text-sm font-bold\">${item.title}</p>\n <p class=\"text-sm\">${item.description}</p>\n </div>\n </div>\n <div class=\"w-1/4\">\n <img src=\"${imgUrl}\" alt=\"${item.label}-alt\" class=\"w-14 h-14\" />\n </div>`\n }\n\n return html`<div class=\"h-[300px] overflow-y-scroll\">\n ${notificationList.map(\n item =>\n html`<button\n class=\"flex w-full text-left items-start p-4 cursor-pointer justify-between ${!item.isRead\n ? 'bg-blue-100'\n : ''}\"\n @click=${() => this.redirectTo(item.notificationId, item.link)}\n >\n ${notificationInfoListTemplate(item)}\n </button> `\n )}\n </div>\n <!-- Footer Link -->\n <div class=\"px-4 py-4 text-center\">\n <a href=\"#\" @click=\"${() =>\n this.redirectToNotification(\n 'info'\n )}\" class=\"text-base font-bold text-blue-500\">\n Lihat Selengkapnya</a\n >\n </div>\n </div>`\n }\n\n private redirectToNotification(tab: string) {\n window.open(\n `https://account.kompas.id/manage-account/notification/${tab}`,\n '_blank'\n )\n }\n\n // Notification Content\n private notificationContentSection() {\n // Empty state\n if (!this.notificationContentData.length) {\n return html`\n <div class=\"text-center px-4 pt-6 pb-32\">\n <img\n src=\"../../assets/empty-state-notification.png\"\n alt=\"empty-state-notification\"\n class=\"w-auto mx-auto\"\n />\n <p class=\"font-bold text-center text-lg py-2\">Belum Ada Notifikasi</p>\n <p class=\"px-2\">\n Kami akan memberitahukan Anda ketika ada informasi dan pemberitahuan\n terbaru.\n </p>\n </div>\n `\n }\n const notificationContentListTemplate = (item: any) => html`<div\n class=\"w-3/4 pr-1 \"\n >\n <div class=\"flex items-center mb-1 text-xs\">\n <span class=\"text-green-500 bg-green-100 rounded-sm p-1 px-2\">\n ${item.category[0].name}\n </span>\n <span class=\"text-grey-400 ml-2\">\n ${this.formatDate(item.publishedDateGmt)}</span\n >\n </div>\n <p class=\"font-bold text-base text-customTextColor py-1\">\n ${item.title}\n </p>\n </div>\n <div class=\"w-1/4\">\n <img\n src=\"${item.thumbnails.sizes.thumbnailSquareMedium.permalink}\"\n alt=\"content-img-alt\"\n class=\"w-14 h-14 object-cover\"\n />\n </div>`\n\n return html`<div class=\"h-[300px] overflow-y-scroll\">\n ${this.notificationContentData.map(\n item =>\n html`<button\n class=\"flex w-full text-left items-start p-4 cursor-pointer justify-between ${!item.isRead\n ? 'bg-blue-100'\n : ''}\"\n @click=${() => window.open(item.permalink, '_blank')}\n >\n ${notificationContentListTemplate(item)}\n </button> `\n )}\n </div>\n <!-- Footer Link -->\n <div class=\"px-4 py-4 text-center\">\n <a href=\"#\" @click=\"${() =>\n this.redirectToNotification(\n 'konten'\n )}\" class=\"text-base font-bold text-blue-500\">\n Lihat Selengkapnya</a\n >\n </div>\n </div>`\n }\n\n private notificationPopup() {\n const tab = ['Info', 'Konten']\n\n return html`\n <div\n id=\"notificationPopup\"\n class=\"header-notificaion-dropdown rounded-lg shadow-lg z-50 mt-2 ${this\n .isShowDropdown\n ? 'active'\n : ''}\"\n >\n <div class=\"sticky\">\n <div class=\"flex justify-center py-2 border-b border-grey-300\">\n <span class=\"font-bold text-base\">Notifikasi</span>\n </div>\n <!-- Tabs for Info and Content -->\n <div class=\"flex justify-between\">\n ${tab.map(\n item =>\n html`\n <button\n class=\"focus:outline-none py-2 w-1/2 ${this.selectedTab ===\n item && 'link-active'}\"\n @click=${() => this.handleClick(item)}\n >\n ${item}\n </button>\n `\n )}\n </div>\n </div>\n\n <!-- Notification Content -->\n ${this.selectedTab === 'Info'\n ? this.notificationInfoSection()\n : this.notificationContentSection()}\n </div>\n `\n }\n\n render() {\n return html`<div id=\"headerNotification\" class=\"relative\">\n ${this.isDataLoaded\n ? this.notificationIcon()\n : html`<div class=\"text-white cursor-pointer mt-0.5 animate-spin\">\n ${unsafeSVG(getFontAwesomeIcon('fa', 'circle-notch', 21, 21))}\n </div>`}\n ${this.isShowDropdown ? this.notificationPopup() : ''}\n </div>`\n }\n}\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface NotificationList {
|
|
2
|
+
notificationId: string;
|
|
3
|
+
id: number;
|
|
4
|
+
title: string;
|
|
5
|
+
label: string;
|
|
6
|
+
description: string;
|
|
7
|
+
isRead: boolean;
|
|
8
|
+
time: string;
|
|
9
|
+
link: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UserNotification {
|
|
12
|
+
notificationList: NotificationList[];
|
|
13
|
+
notificationCount: number;
|
|
14
|
+
loadMore: boolean;
|
|
15
|
+
next: number;
|
|
16
|
+
}
|
|
17
|
+
interface Meta {
|
|
18
|
+
cache: boolean;
|
|
19
|
+
time: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ApiResponse<T> {
|
|
22
|
+
success: boolean;
|
|
23
|
+
code: number;
|
|
24
|
+
message: string;
|
|
25
|
+
meta: Meta;
|
|
26
|
+
data: T;
|
|
27
|
+
}
|
|
28
|
+
export interface ApiRubrikResponse<T> {
|
|
29
|
+
success: boolean;
|
|
30
|
+
code: number;
|
|
31
|
+
message: string;
|
|
32
|
+
meta: Meta;
|
|
33
|
+
result: T;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/components/kompasid-header-notification/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface NotificationList {\n notificationId: string\n id: number\n title: string\n label: string\n description: string\n isRead: boolean\n time: string // ISO date string\n link: string\n}\n\n// Interface for the overall notification state\nexport interface UserNotification {\n notificationList: NotificationList[]\n notificationCount: number\n loadMore: boolean\n next: number\n}\n\ninterface Meta {\n cache: boolean\n time: number\n}\n\nexport interface ApiResponse<T> {\n success: boolean\n code: number\n message: string\n meta: Meta\n data: T\n}\n\nexport interface ApiRubrikResponse<T> {\n success: boolean\n code: number\n message: string\n meta: Meta\n result: T\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface ApiResponse<T> extends Response {
|
|
2
|
+
json(): Promise<T>;
|
|
3
|
+
}
|
|
4
|
+
interface RequestInit {
|
|
5
|
+
method?: string;
|
|
6
|
+
headers?: Headers | {
|
|
7
|
+
[key: string]: string;
|
|
8
|
+
};
|
|
9
|
+
body?: BodyInit | null;
|
|
10
|
+
mode?: RequestMode;
|
|
11
|
+
credentials?: RequestCredentials;
|
|
12
|
+
cache?: RequestCache;
|
|
13
|
+
redirect?: RequestRedirect;
|
|
14
|
+
referrer?: string;
|
|
15
|
+
referrerPolicy?: ReferrerPolicy;
|
|
16
|
+
integrity?: string;
|
|
17
|
+
keepalive?: boolean;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}
|
|
20
|
+
export declare function customFetch<T>(url: string, refreshToken: string, accessToken: string, options?: RequestInit): Promise<ApiResponse<T>>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Function to refresh the token
|
|
2
|
+
async function refreshAccessToken(refreshToken) {
|
|
3
|
+
const response = await fetch('https://api.kompas.cloud/account/api/v1/tokens/refresh', {
|
|
4
|
+
method: 'POST',
|
|
5
|
+
body: JSON.stringify({
|
|
6
|
+
refreshToken,
|
|
7
|
+
}),
|
|
8
|
+
headers: {
|
|
9
|
+
'Content-Type': 'application/json',
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
throw new Error('Failed to refresh token');
|
|
14
|
+
}
|
|
15
|
+
const data = await response.json();
|
|
16
|
+
return data.data.accessToken;
|
|
17
|
+
}
|
|
18
|
+
// Custom fetch function that retries after 401
|
|
19
|
+
export async function customFetch(url, refreshToken, accessToken, options = {}) {
|
|
20
|
+
try {
|
|
21
|
+
// Retrieve and set access token in headers
|
|
22
|
+
const headers = new Headers(options.headers || {});
|
|
23
|
+
if (accessToken) {
|
|
24
|
+
headers.set('Authorization', `Bearer ${accessToken}`);
|
|
25
|
+
}
|
|
26
|
+
// Set updated headers
|
|
27
|
+
options.headers = headers;
|
|
28
|
+
let response = await fetch(url, options);
|
|
29
|
+
// Retry request if 401 error occurs
|
|
30
|
+
if (response.status === 401) {
|
|
31
|
+
const newToken = await refreshAccessToken(refreshToken);
|
|
32
|
+
headers.set('Authorization', `Bearer ${newToken}`);
|
|
33
|
+
// Retry the original request with the new token
|
|
34
|
+
response = await fetch(url, { ...options, headers });
|
|
35
|
+
}
|
|
36
|
+
return response;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Error making API call:', error);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/components/kompasid-header-notification/utils.ts"],"names":[],"mappings":"AA+BA,gCAAgC;AAChC,KAAK,UAAU,kBAAkB,CAAC,YAAoB;IACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,wDAAwD,EACxD;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,YAAY;SACb,CAAC;QACF,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;SACnC;KACF,CACF,CAAA;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;KAC3C;IAED,MAAM,IAAI,GAAyB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACxD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAA;AAC9B,CAAC;AAED,+CAA+C;AAC/C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAW,EACX,YAAoB,EACpB,WAAmB,EACnB,UAAuB,EAAE;IAEzB,IAAI;QACF,2CAA2C;QAC3C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;QAClD,IAAI,WAAW,EAAE;YACf,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,WAAW,EAAE,CAAC,CAAA;SACtD;QAED,sBAAsB;QACtB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAA;QACzB,IAAI,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAExC,oCAAoC;QACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;YAC3B,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,YAAY,CAAC,CAAA;YACvD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,QAAQ,EAAE,CAAC,CAAA;YAClD,gDAAgD;YAChD,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;SACrD;QAED,OAAO,QAA0B,CAAA;KAClC;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;QAC9C,MAAM,KAAK,CAAA;KACZ;AACH,CAAC","sourcesContent":["/* eslint-disable no-param-reassign */\n/* eslint-disable no-undef */\n// Define types for the API responses\ninterface RefreshTokenResponse {\n data: {\n accessToken: string\n deviceKeyId: string\n isVerified: boolean\n refreshToken: string\n }\n}\n\ninterface ApiResponse<T> extends Response {\n json(): Promise<T>\n}\n\ninterface RequestInit {\n method?: string\n headers?: Headers | { [key: string]: string }\n body?: BodyInit | null\n mode?: RequestMode\n credentials?: RequestCredentials\n cache?: RequestCache\n redirect?: RequestRedirect\n referrer?: string\n referrerPolicy?: ReferrerPolicy\n integrity?: string\n keepalive?: boolean\n signal?: AbortSignal\n}\n\n// Function to refresh the token\nasync function refreshAccessToken(refreshToken: string): Promise<string> {\n const response = await fetch(\n 'https://api.kompas.cloud/account/api/v1/tokens/refresh',\n {\n method: 'POST',\n body: JSON.stringify({\n refreshToken,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n\n if (!response.ok) {\n throw new Error('Failed to refresh token')\n }\n\n const data: RefreshTokenResponse = await response.json()\n return data.data.accessToken\n}\n\n// Custom fetch function that retries after 401\nexport async function customFetch<T>(\n url: string,\n refreshToken: string,\n accessToken: string,\n options: RequestInit = {}\n): Promise<ApiResponse<T>> {\n try {\n // Retrieve and set access token in headers\n const headers = new Headers(options.headers || {})\n if (accessToken) {\n headers.set('Authorization', `Bearer ${accessToken}`)\n }\n\n // Set updated headers\n options.headers = headers\n let response = await fetch(url, options)\n\n // Retry request if 401 error occurs\n if (response.status === 401) {\n const newToken = await refreshAccessToken(refreshToken)\n headers.set('Authorization', `Bearer ${newToken}`)\n // Retry the original request with the new token\n response = await fetch(url, { ...options, headers })\n }\n\n return response as ApiResponse<T>\n } catch (error) {\n console.error('Error making API call:', error)\n throw error\n }\n}\n"]}
|
|
@@ -469,7 +469,8 @@ let KompasIdPaywallBody = class KompasIdPaywallBody extends LitElement {
|
|
|
469
469
|
let buttonContent;
|
|
470
470
|
const textColorClass = this.isDark ? 'text-blue-300' : 'text-blue-600';
|
|
471
471
|
const buttonTextColorClass = this.isDark ? 'text-white' : 'text-grey-600';
|
|
472
|
-
|
|
472
|
+
const isPrevHistoryExist = window.history.length > 1;
|
|
473
|
+
if (type === 'epaper' && isPrevHistoryExist) {
|
|
473
474
|
buttonContent = html ` <button
|
|
474
475
|
@click=${this.redirectToPrevUrl}
|
|
475
476
|
class="hidden md:block w-8 h-8 pl-4 ${textColorClass}"
|