// — CONFIGURATION START —
const TOTAL_DAYS = 12;
// Start Date: Year, Month (0-11), Day
const START_YEAR = 2025;
const START_MONTH = 11; // December
const START_DAY = 13; // Updated to start on Dec 13th (so Day 12 is Dec 24th)
// EDIT PRIZES HERE
let prizes = [
// 4 Coupons
{ type: “coupon”, text: “Save 5% on your purchase from @traderbea using the code 5PM20. Max $20 Savings Expires Christmas Day 11:59PM CDT”, code: “5PM20”, emoji: “🐝” },
{ type: “coupon”, text: “Save 10% on your purchase from @traderbea using the code 10PM20. Max $20 Savings Expires Christmas Day 11:59PM CDT”, code: “10PM20”, emoji: “🍯” },
{ type: “coupon”, text: “Save $5.00 on your purchases $20 and up from @traderbea using the code 5D20M. Savings Expire Christmas Day 11:59 CDT”, code: “5D20M”, emoji: “💵” },
{ type: “coupon”, text: “$20.00 discount on orders over $100.00 using code 20D100M. Savings Expire Christmas Day 11:59 CDT”, code: “20D100M”, emoji: “🎁” },
// 3 Holiday Surprise Videos
{ type: “link”, text: “Holiday Surprise Video”, code: “WATCH”, emoji: “📺”, url: “https://youtu.be/zDP6J5l7b-o” },
{ type: “link”, text: “Holiday Surprise Video”, code: “WATCH”, emoji: “📺”, url: “https://youtu.be/uMT08q8DuvI” },
{ type: “link”, text: “Holiday Surprise Video”, code: “WATCH”, emoji: “📺”, url: “https://youtu.be/HwgAnUPigZs” },
// 5 Trader Bea Songs by One_Time
{ type: “link”, text: “Trader Bea Song by One_Time”, code: “LISTEN”, emoji: “🎵”, url: “https://youtube.com/shorts/qvIYgK0Wd0w?feature=share” },
{ type: “link”, text: “Trader Bea Song by One_Time”, code: “LISTEN”, emoji: “🎵”, url: “https://youtube.com/shorts/ZPRP6EQ1-Ws?feature=share” },
{ type: “link”, text: “Trader Bea Song by One_Time”, code: “LISTEN”, emoji: “🎵”, url: “https://youtu.be/yepiCcf3z6s” },
{ type: “link”, text: “Trader Bea Song by One_Time”, code: “LISTEN”, emoji: “🎵”, url: “https://youtu.be/f3HDs9U8ODI” },
{ type: “link”, text: “Trader Bea Song by One_Time”, code: “LISTEN”, emoji: “🎵”, url: “https://youtu.be/pPGTpzhIOFc” }
];
// — CONFIGURATION END —
let testMode = false;
// — SAFE STORAGE HANDLER (Prevents crashes if LocalStorage is blocked) —
const safeStorage = {
getItem: (key) => {
try {
return localStorage.getItem(key);
} catch (e) {
console.warn(“LocalStorage blocked. Using temporary memory.”);
return null;
}
},
setItem: (key, val) => {
try {
localStorage.setItem(key, val);
} catch (e) {
// Fail silently
}
},
removeItem: (key) => {
try {
localStorage.removeItem(key);
} catch (e) {
// Fail silently
}
}
};
// Load State – V12 (Hidden Button Update)
let state = JSON.parse(safeStorage.getItem(‘traderBeaState_v12’)) || {
openedDoors: [],
prizeOrder: null
};
if (!state.prizeOrder) {
shuffleArray(prizes);
state.prizeOrder = prizes;
safeStorage.setItem(‘traderBeaState_v12’, JSON.stringify(state));
}
console.log(“🎴 Current Prize Order for this session:”, state.prizeOrder);
const grid = document.getElementById(‘calendar-grid’);
const statusBar = document.getElementById(‘status-bar’);
function saveState() {
safeStorage.setItem(‘traderBeaState_v12’, JSON.stringify(state));
}
function getUnlockDate(dayNum) {
const date = new Date(START_YEAR, START_MONTH, START_DAY, 0, 0, 0);
date.setDate(date.getDate() + (dayNum – 1));
return date;
}
function renderCalendar() {
grid.innerHTML = ”;
const now = new Date();
let nextUnlockDate = null;
for (let dayNum = 1; dayNum = unlockDate);
if (!isUnlocked && nextUnlockDate === null) {
nextUnlockDate = unlockDate;
}
const hexWrapper = document.createElement(‘div’);
hexWrapper.className = ‘hex-wrapper’;
const hex = document.createElement(‘div’);
let statusClass = ”;
if (isOpened) statusClass = ‘opened’;
else if (!isUnlocked) statusClass = ‘locked’;
hex.className = `hex ${statusClass}`;
hex.onclick = () => handleDoorClick(dayNum, hex, unlockDate, prize);
// Content
const daySpan = document.createElement(‘span’);
daySpan.className = ‘day-number’;
daySpan.innerText = dayNum;
// Hidden Content (Simplified for Grid View)
const treatDiv = document.createElement(‘div’);
treatDiv.className = ‘treat’;
treatDiv.innerHTML = `
${prize.emoji}
OPENED
`;
hex.appendChild(daySpan);
hex.appendChild(treatDiv);
hexWrapper.appendChild(hex);
grid.appendChild(hexWrapper);
}
updateStatusHeader(now, nextUnlockDate);
}
function updateStatusHeader(now, nextUnlockDate) {
if (testMode) {
statusBar.innerText = “TEST MODE: All Unlocked”;
return;
}
const startDate = getUnlockDate(1);
if (now < startDate) {
// Dynamic date display
statusBar.innerText = `Event Starts: ${startDate.toLocaleDateString()}`;
} else if (nextUnlockDate) {
const diff = nextUnlockDate – now;
statusBar.innerHTML = `Next Day Unlocks: ${formatTime(diff)}`;
} else {
statusBar.innerText = “Merry Christmas! All days unlocked.”;
}
}
function handleDoorClick(day, element, unlockDate, prize) {
const now = new Date();
const isOpened = state.openedDoors.includes(day);
// 1. If Locked (and not test mode)
if (!isOpened && !testMode && now element.classList.remove(‘shake’), 500);
const diff = unlockDate – now;
showModal(“Patience, Honeybee!”, `Day ${day} unlocks on ${unlockDate.toLocaleDateString()} at 12:00 AM.`, diff);
return;
}
// 2. Open logic (if not already opened)
if (!isOpened) {
openDoor(day, element);
}
// 3. SHOW THE LARGE REWARD CARD
showPrizeModal(day, prize);
}
// Helper to get YouTube ID from URL (Updated to support Shorts)
function getYoutubeId(url) {
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=|shorts\/)([^#&?]*).*/;
const match = url.match(regExp);
return (match && match[2].length === 11) ? match[2] : null;
}
function showPrizeModal(dayNum, prize) {
const title = `Day ${dayNum} Reward!`;
let actionContent = ”;
// Check if it’s a link and specifically a valid URL
if(prize.type === ‘link’ && prize.url && prize.url !== ‘#’) {
// Try to get YouTube ID
const videoId = getYoutubeId(prize.url);
if (videoId) {
// It is a YouTube video -> Show Thumbnail
const thumbUrl = `https://img.youtube.com/vi/${videoId}/mqdefault.jpg`;
actionContent = `
`;
} else {
// Not a YouTube link (or failed to parse) -> Show Button
actionContent = `▶ OPEN LINK`;
}
} else {
// It’s a coupon code
actionContent = `
${prize.code}
`;
}
const content = `
${prize.emoji}
${prize.text}
${actionContent}
(Saved to Day ${dayNum})
`;
showModal(title, content, null);
}
function openDoor(day, element) {
state.openedDoors.push(day);
saveState();
renderCalendar();
}
function updateTimers() {
const now = new Date();
const headerTimer = document.getElementById(‘header-timer’);
if (headerTimer) {
for (let i = 1; i <= TOTAL_DAYS; i++) {
const d = getUnlockDate(i);
if (now < d) {
headerTimer.innerText = formatTime(d – now);
break;
}
}
}
// Modal timer logic included…
if(document.getElementById('modal-timer').style.display === 'block' && activeModalTargetDate) {
const diff = activeModalTargetDate – now;
if(diff <= 0) closeModal();
else document.getElementById('modal-timer').innerText = formatTime(diff);
}
}
let activeModalTargetDate = null;
function formatTime(ms) {
if (ms 0) return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
}
function pad(n) { return n 0; i–) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function showModal(title, msgHtml, timeRemainingMs) {
document.getElementById(‘modal-title’).innerText = title;
document.getElementById(‘modal-msg’).innerHTML = msgHtml; // Changed to innerHTML for custom content
if (timeRemainingMs) {
activeModalTargetDate = new Date(Date.now() + timeRemainingMs);
document.getElementById(‘modal-timer’).innerText = formatTime(timeRemainingMs);
document.getElementById(‘modal-timer’).style.display = ‘block’;
} else {
activeModalTargetDate = null;
document.getElementById(‘modal-timer’).style.display = ‘none’;
}
document.getElementById(‘overlay’).classList.add(‘active’);
document.getElementById(‘modal’).classList.add(‘active’);
}
function closeModal() {
document.getElementById(‘overlay’).classList.remove(‘active’);
document.getElementById(‘modal’).classList.remove(‘active’);
activeModalTargetDate = null;
}
function resetCalendar() {
if(confirm(“Reset progress? This will lock all days again and reshuffle prizes.”)) {
safeStorage.removeItem(‘traderBeaState_v12’);
testMode = false;
document.getElementById(‘testModeBtn’).innerText = ‘Test Mode: OFF’;
document.getElementById(‘testModeBtn’).style.display = ‘none’; // Re-hide button
location.reload();
// Fallback
state = { openedDoors: [], prizeOrder: null };
let freshPrizes = […prizes];
shuffleArray(freshPrizes);
state.prizeOrder = freshPrizes;
saveState();
renderCalendar();
}
}
function toggleTestMode() {
testMode = !testMode;
document.getElementById(‘testModeBtn’).innerText = `Test Mode: ${testMode ? ‘ON’ : ‘OFF’}`;
renderCalendar();
}
// — SECRET ADMIN TRIGGER —
let tapCount = 0;
let tapTimer = null;
// Listen for clicks on the H1 Title
document.querySelector(‘h1’).addEventListener(‘click’, () => {
tapCount++;
if(tapCount === 1) {
// Start a 2 second timer to reset taps
tapTimer = setTimeout(() => { tapCount = 0; }, 2000);
}
if(tapCount >= 5) {
// 5 taps detected!
document.getElementById(‘testModeBtn’).style.display = ‘inline-block’;
alert(“Admin Mode Revealed: Test button is now visible below.”);
tapCount = 0;
clearTimeout(tapTimer);
}
});
// Also check URL for ?admin=true
const urlParams = new URLSearchParams(window.location.search);
if(urlParams.get(‘admin’) === ‘true’) {
document.getElementById(‘testModeBtn’).style.display = ‘inline-block’;
}
renderCalendar();