class FreeShippingBar extends HTMLElement {
constructor() {
super();
// Initialize properties with error handling
try {
this.threshold = parseInt(this.dataset.freeShippingThreshold) || 10000;
this.progressFill = this.querySelector('.free-shipping-bar__progress-fill');
this.message = this.querySelector('.free-shipping-bar__message');
this.messageText = this.querySelector('.free-shipping-bar__text');
this.progressText = this.querySelector('.free-shipping-bar__progress-text');
this.progressSection = this.querySelector('.free-shipping-bar__progress');
this.init();
} catch (error) {
console.error('FreeShippingBar: Error in constructor:', error);
}
}
init() {
try {
// Subscribe to cart updates with error filtering
this.cartUpdateUnsubscriber = subscribe(PUB_SUB_EVENTS.cartUpdate, (event) => {
if (event?.cartData && !event.cartData.errors) {
this.updateFreeShippingBar(event);
}
});
} catch (error) {
console.error('FreeShippingBar: Error in init:', error);
}
}
disconnectedCallback() {
try {
if (this.cartUpdateUnsubscriber) {
this.cartUpdateUnsubscriber();
}
} catch (error) {
console.error('FreeShippingBar: Error in disconnectedCallback:', error);
}
}
updateFreeShippingBar(event) {
try {
if (!event?.cartData?.total_price) return;
const cartTotal = event.cartData.total_price;
const remainingAmount = this.threshold - cartTotal;
const progressPercentage = Math.min((cartTotal / this.threshold) * 100, 100);
// Update progress bar
this.updateProgressBar(progressPercentage);
// Update message based on qualification status
if (remainingAmount <= 0) {
this.showQualifiedMessage();
} else {
this.showProgressMessage(remainingAmount, cartTotal);
}
} catch (error) {
console.error('FreeShippingBar: Error updating free shipping bar:', error);
}
}
updateProgressBar(percentage) {
if (this.progressFill) {
this.progressFill.style.width = `${percentage}%`;
this.progressFill.dataset.progress = percentage;
}
}
showQualifiedMessage() {
try {
if (!this.message) return;
this.message.classList.add('free-shipping-bar__message--success');
this.message.innerHTML = `
${this.getQualifiedMessage()}
`;
this.hideProgressSection();
} catch (error) {
console.error('FreeShippingBar: Error showing qualified message:', error);
}
}
showProgressMessage(remainingAmount, cartTotal) {
try {
if (!this.message) return;
this.message.classList.remove('free-shipping-bar__message--success');
this.message.innerHTML = `
${this.formatMessage(this.getProgressMessage(), remainingAmount)}
`;
this.showProgressSection();
this.updateProgressText(cartTotal);
} catch (error) {
console.error('FreeShippingBar: Error showing progress message:', error);
}
}
getQualifiedMessage() {
return window.freeShippingStrings?.free_shipping_qualified ||
"🎉 Congrats! You've unlocked Free Gift";
}
getProgressMessage() {
return window.freeShippingStrings?.free_shipping_progress ||
"You're only {{ amount }} away from Free Gift";
}
getProgressTextTemplate() {
return window.freeShippingStrings?.free_shipping_progress_text ||
"{{ current }} of {{ threshold }}";
}
updateProgressText(cartTotal) {
if (this.progressText) {
this.progressText.innerHTML = this.formatMessage(
this.getProgressTextTemplate(),
cartTotal,
this.threshold
);
}
}
showProgressSection() {
if (this.progressSection) {
this.progressSection.style.display = 'flex';
}
}
hideProgressSection() {
if (this.progressSection) {
this.progressSection.style.display = 'none';
}
}
formatMessage(template, ...values) {
try {
if (!template) return '';
let message = template;
if (values.length === 1) {
// Single value (remaining amount)
message = message.replace(/\{\{\s*amount\s*\}\}/g, this.formatMoney(values[0]));
} else if (values.length === 2) {
// Two values (current and threshold)
message = message.replace(/\{\{\s*current\s*\}\}/g, this.formatMoney(values[0]));
message = message.replace(/\{\{\s*threshold\s*\}\}/g, this.formatMoney(values[1]));
}
return message;
} catch (error) {
console.error('FreeShippingBar: Error formatting message:', error);
return template || '';
}
}
formatMoney(amount) {
try {
if (typeof amount !== 'number' || isNaN(amount)) {
return '$0.00';
}
// Convert cents to dollars and format
const dollars = (amount / 100).toFixed(2);
return `$${dollars}`;
} catch (error) {
console.error('FreeShippingBar: Error formatting money:', error);
return '$0.00';
}
}
}
customElements.define('free-shipping-bar', FreeShippingBar);