udpate
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Flip-style countdown for landing pages.
|
||||
* Usage:
|
||||
* <div class="landing-countdown" data-countdown data-countdown-end="2026-12-31T23:59:59">
|
||||
* <div class="landing-countdown" data-countdown data-countdown-days="10">
|
||||
*/
|
||||
(function () {
|
||||
function pad2(n) {
|
||||
return String(Math.max(0, n)).padStart(2, "0");
|
||||
}
|
||||
|
||||
function renderDigits(container, value) {
|
||||
var digits = container.querySelectorAll("[data-countdown-digit]");
|
||||
var str = pad2(value);
|
||||
digits[0].textContent = str[0];
|
||||
digits[1].textContent = str[1];
|
||||
}
|
||||
|
||||
function resolveEndTime(el) {
|
||||
var daysAttr = el.getAttribute("data-countdown-days");
|
||||
if (daysAttr != null && daysAttr !== "") {
|
||||
var days = parseInt(daysAttr, 10);
|
||||
if (!Number.isNaN(days) && days >= 0) {
|
||||
var end = new Date();
|
||||
end.setDate(end.getDate() + days);
|
||||
end.setHours(23, 59, 59, 999);
|
||||
return end.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
var endStr = el.getAttribute("data-countdown-end");
|
||||
if (!endStr) return NaN;
|
||||
return new Date(endStr).getTime();
|
||||
}
|
||||
|
||||
function initCountdown(el) {
|
||||
var end = resolveEndTime(el);
|
||||
if (Number.isNaN(end)) return;
|
||||
|
||||
var daysEl = el.querySelector("[data-countdown-days]");
|
||||
var hoursEl = el.querySelector("[data-countdown-hours]");
|
||||
var minsEl = el.querySelector("[data-countdown-mins]");
|
||||
var secsEl = el.querySelector("[data-countdown-secs]");
|
||||
|
||||
function tick() {
|
||||
var diff = Math.max(0, end - Date.now());
|
||||
var totalSec = Math.floor(diff / 1000);
|
||||
var days = Math.floor(totalSec / 86400);
|
||||
var hours = Math.floor((totalSec % 86400) / 3600);
|
||||
var mins = Math.floor((totalSec % 3600) / 60);
|
||||
var secs = totalSec % 60;
|
||||
|
||||
if (daysEl) renderDigits(daysEl, days);
|
||||
if (hoursEl) renderDigits(hoursEl, hours);
|
||||
if (minsEl) renderDigits(minsEl, mins);
|
||||
if (secsEl) renderDigits(secsEl, secs);
|
||||
}
|
||||
|
||||
tick();
|
||||
setInterval(tick, 1000);
|
||||
}
|
||||
|
||||
function initAll() {
|
||||
document.querySelectorAll("[data-countdown]").forEach(initCountdown);
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initAll);
|
||||
} else {
|
||||
initAll();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Welcome rewards floor — loads landing-welcome-rewards.section.html
|
||||
* and fills copy from data-* on the placeholder node.
|
||||
*
|
||||
* Placeholder example:
|
||||
* <div
|
||||
* data-landing-welcome-rewards
|
||||
* data-welcome-title-id="dollar-welcome-title"
|
||||
* data-welcome-title-before="Welcome"
|
||||
* data-welcome-title-accent="rewards"
|
||||
* data-welcome-eyebrow="Limited-time offer"
|
||||
* data-welcome-value="$1"
|
||||
* data-welcome-sub="ALL CHALLENGES*"
|
||||
* data-welcome-code-label="Use code"
|
||||
* data-welcome-code="AIFOPROM"
|
||||
* data-welcome-cta-text="Claim Now"
|
||||
* data-welcome-cta-href="#register-now"
|
||||
* data-welcome-copy-success="Code copied!"
|
||||
* ></div>
|
||||
*/
|
||||
(function () {
|
||||
var MODULE_URL = '/pages/modules/landing-welcome-rewards.section.html';
|
||||
var DEFAULT_COPY_SUCCESS = 'Code copied to clipboard!';
|
||||
var copyToastTimer;
|
||||
|
||||
function readConfig(el) {
|
||||
return {
|
||||
titleId: el.getAttribute('data-welcome-title-id') || 'landing-welcome-title',
|
||||
titleBefore: el.getAttribute('data-welcome-title-before') || '',
|
||||
titleAccent: el.getAttribute('data-welcome-title-accent') || '',
|
||||
eyebrow: el.getAttribute('data-welcome-eyebrow') || '',
|
||||
value: el.getAttribute('data-welcome-value') || '',
|
||||
sub: el.getAttribute('data-welcome-sub') || '',
|
||||
codeLabel: el.getAttribute('data-welcome-code-label') || '',
|
||||
code: el.getAttribute('data-welcome-code') || '',
|
||||
ctaText: el.getAttribute('data-welcome-cta-text') || '',
|
||||
ctaHref: el.getAttribute('data-welcome-cta-href') || '#register-now',
|
||||
note: el.getAttribute('data-welcome-note') || '',
|
||||
copySuccess: el.getAttribute('data-welcome-copy-success') || DEFAULT_COPY_SUCCESS,
|
||||
};
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
if (!text) return Promise.resolve();
|
||||
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
|
||||
return navigator.clipboard.writeText(text);
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = text;
|
||||
ta.setAttribute('readonly', '');
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.left = '-9999px';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
try {
|
||||
if (document.execCommand('copy')) resolve();
|
||||
else reject(new Error('copy failed'));
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
} finally {
|
||||
document.body.removeChild(ta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getCopyToast() {
|
||||
var toast = document.getElementById('landing-welcome-copy-toast');
|
||||
if (toast) return toast;
|
||||
|
||||
toast = document.createElement('div');
|
||||
toast.id = 'landing-welcome-copy-toast';
|
||||
toast.className = 'landing-welcome-copy-toast';
|
||||
toast.setAttribute('role', 'status');
|
||||
toast.setAttribute('aria-live', 'polite');
|
||||
document.body.appendChild(toast);
|
||||
return toast;
|
||||
}
|
||||
|
||||
function showCopyToast(message) {
|
||||
var toast = getCopyToast();
|
||||
toast.textContent = message;
|
||||
toast.classList.add('is-visible');
|
||||
window.clearTimeout(copyToastTimer);
|
||||
copyToastTimer = window.setTimeout(function () {
|
||||
toast.classList.remove('is-visible');
|
||||
}, 2400);
|
||||
}
|
||||
|
||||
function bindPromoCodeCopy(codeEl, config) {
|
||||
if (!codeEl || !config.code) return;
|
||||
|
||||
codeEl.setAttribute('aria-label', 'Copy promo code ' + config.code);
|
||||
|
||||
codeEl.addEventListener('click', function () {
|
||||
copyText(config.code)
|
||||
.then(function () {
|
||||
codeEl.classList.add('is-copied');
|
||||
showCopyToast(config.copySuccess);
|
||||
window.setTimeout(function () {
|
||||
codeEl.classList.remove('is-copied');
|
||||
}, 1200);
|
||||
})
|
||||
.catch(function () {
|
||||
showCopyToast('Copy failed. Please copy manually.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setText(node, value) {
|
||||
if (!node) return;
|
||||
node.textContent = value;
|
||||
}
|
||||
|
||||
function populateSection(section, config) {
|
||||
section.setAttribute('aria-labelledby', config.titleId);
|
||||
|
||||
var titleEl = section.querySelector('[data-welcome-title]');
|
||||
if (titleEl) {
|
||||
titleEl.id = config.titleId;
|
||||
titleEl.textContent = '';
|
||||
|
||||
if (config.titleBefore) {
|
||||
titleEl.appendChild(document.createTextNode(config.titleBefore));
|
||||
}
|
||||
|
||||
if (config.titleAccent) {
|
||||
if (config.titleBefore) {
|
||||
titleEl.appendChild(document.createTextNode(' '));
|
||||
}
|
||||
var accent = document.createElement('span');
|
||||
accent.className = 'landing-accent';
|
||||
accent.textContent = config.titleAccent;
|
||||
titleEl.appendChild(accent);
|
||||
}
|
||||
}
|
||||
|
||||
setText(section.querySelector('[data-welcome-eyebrow]'), config.eyebrow);
|
||||
setText(section.querySelector('[data-welcome-value]'), config.value);
|
||||
setText(section.querySelector('[data-welcome-sub]'), config.sub);
|
||||
|
||||
var codeWrap = section.querySelector('[data-welcome-code-wrap]');
|
||||
if (codeWrap && (config.codeLabel || config.code)) {
|
||||
codeWrap.hidden = false;
|
||||
setText(section.querySelector('[data-welcome-code-label]'), config.codeLabel);
|
||||
var codeEl = section.querySelector('[data-welcome-code]');
|
||||
setText(codeEl, config.code);
|
||||
bindPromoCodeCopy(codeEl, config);
|
||||
}
|
||||
|
||||
var cta = section.querySelector('[data-welcome-cta]');
|
||||
if (cta && config.ctaText) {
|
||||
cta.hidden = false;
|
||||
cta.textContent = config.ctaText;
|
||||
cta.href = config.ctaHref;
|
||||
}
|
||||
|
||||
var note = section.querySelector('[data-welcome-note]');
|
||||
if (note && config.note) {
|
||||
note.hidden = false;
|
||||
note.textContent = config.note;
|
||||
}
|
||||
}
|
||||
|
||||
function loadLandingWelcomeRewardsModule() {
|
||||
var placeholder = document.querySelector('[data-landing-welcome-rewards]');
|
||||
if (!placeholder) return;
|
||||
|
||||
var config = readConfig(placeholder);
|
||||
var parent = placeholder.parentNode;
|
||||
|
||||
fetch(MODULE_URL, { credentials: 'same-origin' })
|
||||
.then(function (res) {
|
||||
if (!res.ok) throw new Error('Failed to load ' + MODULE_URL);
|
||||
return res.text();
|
||||
})
|
||||
.then(function (html) {
|
||||
var wrap = document.createElement('div');
|
||||
wrap.innerHTML = html.trim();
|
||||
var section = wrap.firstElementChild;
|
||||
if (!section || !parent) return;
|
||||
|
||||
populateSection(section, config);
|
||||
parent.replaceChild(section, placeholder);
|
||||
document.dispatchEvent(
|
||||
new CustomEvent('aifo:landing-welcome-rewards-ready', { detail: { config: config } })
|
||||
);
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error('[landing-welcome-rewards-module.js]', err);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', loadLandingWelcomeRewardsModule);
|
||||
} else {
|
||||
loadLandingWelcomeRewardsModule();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Loads payout-24h.section.html into #payout-24h-container.
|
||||
*/
|
||||
(function () {
|
||||
var MODULE_URL = '/pages/modules/payout-24h.section.html';
|
||||
|
||||
function loadPayout24hModule() {
|
||||
var container = document.getElementById('payout-24h-container');
|
||||
if (!container) return;
|
||||
|
||||
fetch(MODULE_URL, { credentials: 'same-origin' })
|
||||
.then(function (res) {
|
||||
if (!res.ok) throw new Error('Failed to load ' + MODULE_URL);
|
||||
return res.text();
|
||||
})
|
||||
.then(function (html) {
|
||||
container.innerHTML = html;
|
||||
document.dispatchEvent(new CustomEvent('aifo:payout-24h-ready'));
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error('[payout-24h-module.js]', err);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', loadPayout24hModule);
|
||||
} else {
|
||||
loadPayout24hModule();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user