@cshah18/sdk 3.0.5 → 4.0.0
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/dist/cobuy-sdk.esm.js
CHANGED
|
@@ -304,11 +304,44 @@ class GroupListModal {
|
|
|
304
304
|
this.currentSessionId = null;
|
|
305
305
|
this.onGroupJoined = null;
|
|
306
306
|
this.onViewProgress = null;
|
|
307
|
+
this.socketListenerRegistered = false;
|
|
307
308
|
this.escapeHandler = (event) => {
|
|
308
309
|
if (event.key === "Escape") {
|
|
309
310
|
this.close();
|
|
310
311
|
}
|
|
311
312
|
};
|
|
313
|
+
this.handleGroupMemberJoinedEvent = (event) => {
|
|
314
|
+
this.onGroupMemberJoined(event);
|
|
315
|
+
};
|
|
316
|
+
/** Handle group member joined socket event and update groups list */
|
|
317
|
+
this.onGroupMemberJoined = (event) => {
|
|
318
|
+
const detail = event.detail || {};
|
|
319
|
+
const productId = detail.product_id;
|
|
320
|
+
const groupData = detail.group;
|
|
321
|
+
// Only process if this is for the current product
|
|
322
|
+
if (!productId || !this.currentProductId || productId !== this.currentProductId) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (!groupData) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const groupId = groupData.id;
|
|
329
|
+
const participantsCount = groupData.participants_count;
|
|
330
|
+
if (!groupId) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
// Find and update the group in the list
|
|
334
|
+
const groupIndex = this.groups.findIndex((g) => g.groupId === groupId);
|
|
335
|
+
if (groupIndex !== -1) {
|
|
336
|
+
// Update the joined count
|
|
337
|
+
if (typeof participantsCount === "number") {
|
|
338
|
+
this.groups[groupIndex].joined = participantsCount;
|
|
339
|
+
}
|
|
340
|
+
this.logger.info(`[GroupListModal] Updated group ${groupId} - participants: ${participantsCount}`);
|
|
341
|
+
// Re-render the specific group card
|
|
342
|
+
this.updateGroupCard(groupId);
|
|
343
|
+
}
|
|
344
|
+
};
|
|
312
345
|
this.logger = new Logger(debug);
|
|
313
346
|
this.groups = groups;
|
|
314
347
|
this.liveCount = liveCount;
|
|
@@ -335,6 +368,65 @@ class GroupListModal {
|
|
|
335
368
|
hasGroup(groupId) {
|
|
336
369
|
return this.groups.some((group) => group.groupId === groupId);
|
|
337
370
|
}
|
|
371
|
+
/** Subscribe to socket events for real-time group updates */
|
|
372
|
+
subscribeToSocketEvents() {
|
|
373
|
+
if (typeof window === "undefined" || this.socketListenerRegistered) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
window.addEventListener("group:member:joined", this.handleGroupMemberJoinedEvent);
|
|
377
|
+
this.socketListenerRegistered = true;
|
|
378
|
+
this.logger.debug("[GroupListModal] Socket event listeners registered");
|
|
379
|
+
}
|
|
380
|
+
/** Unsubscribe from socket events */
|
|
381
|
+
unsubscribeFromSocketEvents() {
|
|
382
|
+
if (typeof window === "undefined" || !this.socketListenerRegistered) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
window.removeEventListener("group:member:joined", this.handleGroupMemberJoinedEvent);
|
|
386
|
+
this.socketListenerRegistered = false;
|
|
387
|
+
this.logger.debug("[GroupListModal] Socket event listeners unregistered");
|
|
388
|
+
}
|
|
389
|
+
/** Update the rendered group card with new data */
|
|
390
|
+
updateGroupCard(groupId) {
|
|
391
|
+
if (!this.overlayEl) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const groupCard = this.overlayEl.querySelector(`[data-group-id="${groupId}"]`);
|
|
395
|
+
if (!groupCard) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const group = this.groups.find((g) => g.groupId === groupId);
|
|
399
|
+
if (!group) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
// Update the progress info
|
|
403
|
+
const remaining = Math.max(group.total - group.joined, 0);
|
|
404
|
+
const joinedCountEl = groupCard.querySelector(".cobuy-joined-count");
|
|
405
|
+
const spotsLeftEl = groupCard.querySelector(".cobuy-spots-left");
|
|
406
|
+
if (joinedCountEl) {
|
|
407
|
+
joinedCountEl.textContent = `${group.joined} Joined`;
|
|
408
|
+
}
|
|
409
|
+
if (spotsLeftEl) {
|
|
410
|
+
spotsLeftEl.textContent = `${remaining} ${remaining === 1 ? "spot" : "spots"} left`;
|
|
411
|
+
}
|
|
412
|
+
// Update the progress bar
|
|
413
|
+
const progressFill = groupCard.querySelector(".cobuy-gl-progress-fill");
|
|
414
|
+
if (progressFill) {
|
|
415
|
+
const pct = Math.max(0, Math.min(100, Math.round((group.joined / group.total) * 100)));
|
|
416
|
+
progressFill.style.width = `${pct}%`;
|
|
417
|
+
}
|
|
418
|
+
// Update member avatars
|
|
419
|
+
const membersContainer = groupCard.querySelector(".cobuy-group-members");
|
|
420
|
+
if (membersContainer) {
|
|
421
|
+
// Clear existing avatars
|
|
422
|
+
membersContainer.innerHTML = "";
|
|
423
|
+
// Recreate avatars with updated joined count
|
|
424
|
+
for (let i = 0; i < group.total; i++) {
|
|
425
|
+
const avatar = this.createMemberAvatar(i >= group.joined);
|
|
426
|
+
membersContainer.appendChild(avatar);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
338
430
|
async open(productId, sessionId, joinedGroupId) {
|
|
339
431
|
if (this.overlayEl) {
|
|
340
432
|
this.logger.debug("Group list modal already open");
|
|
@@ -380,6 +472,8 @@ class GroupListModal {
|
|
|
380
472
|
this.overlayEl = overlay;
|
|
381
473
|
document.body.appendChild(overlay);
|
|
382
474
|
document.addEventListener("keydown", this.escapeHandler);
|
|
475
|
+
// Subscribe to socket events for real-time group updates
|
|
476
|
+
this.subscribeToSocketEvents();
|
|
383
477
|
requestAnimationFrame(() => {
|
|
384
478
|
overlay.classList.add("cobuy-gl-open");
|
|
385
479
|
});
|
|
@@ -477,6 +571,8 @@ class GroupListModal {
|
|
|
477
571
|
if (!this.overlayEl) {
|
|
478
572
|
return;
|
|
479
573
|
}
|
|
574
|
+
// Unsubscribe from socket events
|
|
575
|
+
this.unsubscribeFromSocketEvents();
|
|
480
576
|
// Clear any running countdown intervals to avoid leaks
|
|
481
577
|
this.countdownIntervals.forEach((id) => window.clearInterval(id));
|
|
482
578
|
this.countdownIntervals = [];
|
|
@@ -720,6 +816,7 @@ class GroupListModal {
|
|
|
720
816
|
createGroupCard(group) {
|
|
721
817
|
const card = document.createElement("div");
|
|
722
818
|
card.className = "cobuy-group-card";
|
|
819
|
+
card.setAttribute("data-group-id", group.groupId);
|
|
723
820
|
const header = document.createElement("div");
|
|
724
821
|
header.className = "cobuy-group-card-header";
|
|
725
822
|
const groupId = document.createElement("div");
|
|
@@ -3422,6 +3519,7 @@ class WidgetRoot {
|
|
|
3422
3519
|
createWidget(rewardData, container, options) {
|
|
3423
3520
|
const isFulfilled = this.groupFulfilled;
|
|
3424
3521
|
const activeReward = this.frozenReward || (rewardData === null || rewardData === void 0 ? void 0 : rewardData.reward) || null;
|
|
3522
|
+
this.logger.info(`activeReward: ${JSON.stringify(activeReward)}`);
|
|
3425
3523
|
const wrapper = document.createElement("div");
|
|
3426
3524
|
wrapper.className = "cobuy-widget";
|
|
3427
3525
|
wrapper.style.display = "grid";
|
|
@@ -3461,28 +3559,31 @@ class WidgetRoot {
|
|
|
3461
3559
|
rewardLine.style.opacity = "0";
|
|
3462
3560
|
rewardLine.style.animation =
|
|
3463
3561
|
"cobuy-fadeIn var(--cobuy-animation-duration, 300ms) var(--cobuy-animation-easing, ease-out) forwards";
|
|
3464
|
-
if (isFulfilled) {
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
}
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3562
|
+
// if (isFulfilled) {
|
|
3563
|
+
// const rewardText = this.formatRewardText(activeReward);
|
|
3564
|
+
// rewardLine.textContent = rewardText
|
|
3565
|
+
// ? `Reward available: ${rewardText}`
|
|
3566
|
+
// : "Reward available for this group";
|
|
3567
|
+
// rewardLine.setAttribute(
|
|
3568
|
+
// "aria-label",
|
|
3569
|
+
// rewardText ? `Reward locked in: ${rewardText}` : "Reward available for this group",
|
|
3570
|
+
// );
|
|
3571
|
+
// rewardLine.title = rewardLine.textContent;
|
|
3572
|
+
// }
|
|
3573
|
+
// else if (activeReward) {
|
|
3574
|
+
// const rewardText = this.formatRewardText(activeReward);
|
|
3575
|
+
// rewardLine.textContent = rewardText
|
|
3576
|
+
// ? `Save up to ${rewardText} with CoBuy`
|
|
3577
|
+
// : "CoBuy reward available";
|
|
3578
|
+
// rewardLine.setAttribute("aria-label", `Eligible for CoBuy reward: ${rewardLine.textContent}`);
|
|
3579
|
+
// rewardLine.title = rewardLine.textContent;
|
|
3580
|
+
// }
|
|
3581
|
+
// else {
|
|
3582
|
+
// rewardLine.textContent = "CoBuy offer loading or unavailable";
|
|
3583
|
+
// rewardLine.setAttribute("aria-label", "CoBuy offer loading or unavailable");
|
|
3584
|
+
// rewardLine.title = "CoBuy offer loading or unavailable";
|
|
3585
|
+
// rewardLine.style.color = "#6b7280";
|
|
3586
|
+
// }
|
|
3486
3587
|
sections.reward = rewardLine;
|
|
3487
3588
|
// Button - semantic button element with accessibility
|
|
3488
3589
|
const button = document.createElement("button");
|