/**
* 상품 「게임하기 / 구매하기 / 바로구매」 클릭 연결
* - 게임하기 → 즉시 추첨(mode=game)
* - 구매하기 → 상품 상세
* - 결제 승인·추첨 미완료 주문이 있으면 「추첨하기」로 바꾸고 구매 추첨 화면으로 이동
*/
(function () {
var pendingByProduct = null;
var loadPromise = null;
var applyTimer = null;
var mapLoadedOk = false;
function getLoginUser() {
try {
var raw = localStorage.getItem('loginUser');
return raw ? JSON.parse(raw) : null;
} catch (e) {
return null;
}
}
function isLoggedIn() {
return localStorage.getItem('isLoggedIn') === 'true';
}
function waitForFirebase(maxMs) {
var maxWait = maxMs || 10000;
return new Promise(function (resolve) {
var start = Date.now();
function check() {
if (typeof firebase !== 'undefined' && firebase.apps && firebase.apps.length > 0) {
resolve(true);
return;
}
if (Date.now() - start > maxWait) {
resolve(false);
return;
}
setTimeout(check, 80);
}
check();
});
}
function waitForAuthUser(maxMs) {
var maxWait = maxMs || 5000;
return new Promise(function (resolve) {
if (!firebase.auth) {
resolve(null);
return;
}
var existing = firebase.auth().currentUser;
if (existing) {
resolve(existing);
return;
}
var done = false;
var timer = setTimeout(function () {
if (done) return;
done = true;
unsub && unsub();
resolve(firebase.auth().currentUser || null);
}, maxWait);
var unsub = firebase.auth().onAuthStateChanged(function (user) {
if (done) return;
done = true;
clearTimeout(timer);
unsub && unsub();
resolve(user || null);
});
});
}
function purchaseLotteryUrl(orderId, productId) {
var url =
'game-lottery.html?mode=purchase&orderId=' +
encodeURIComponent(orderId || '');
if (productId) {
url += '&id=' + encodeURIComponent(productId);
}
return url;
}
function goPurchaseLottery(orderId, productId) {
if (!orderId) return;
try {
sessionStorage.setItem('purchaseLotteryOrderId', orderId);
if (productId) sessionStorage.setItem('selectedProductId', productId);
} catch (e) { /* ignore */ }
var url = purchaseLotteryUrl(orderId, productId);
if (!isLoggedIn()) {
window.location.href =
'login.html?redirect=' + encodeURIComponent(url);
return;
}
window.location.href = url;
}
function goLottery(productId, mode) {
if (!productId) return;
var nextMode = mode || 'game';
try {
sessionStorage.setItem('selectedProductId', productId);
// 게임하기는 구매 추첨 주문 ID와 섞이면 안 됨
if (nextMode === 'game') {
sessionStorage.removeItem('purchaseLotteryOrderId');
}
} catch (e) { /* ignore */ }
var url =
'game-lottery.html?id=' +
encodeURIComponent(productId) +
'&mode=' +
encodeURIComponent(nextMode);
if (!isLoggedIn()) {
window.location.href =
'login.html?redirect=' + encodeURIComponent(url);
return;
}
window.location.href = url;
}
function goProductDetail(productId) {
if (!productId) return;
try {
sessionStorage.setItem('selectedProductId', productId);
} catch (e) { /* ignore */ }
var url = 'product-detail.html?id=' + encodeURIComponent(productId);
if (!isLoggedIn()) {
window.location.href =
'login.html?redirect=' + encodeURIComponent(url);
return;
}
window.location.href = url;
}
function isOrderOwnedByUser(order, ids) {
if (!order || !ids) return false;
var orderUser = String(order.userId || '').trim();
var orderMember = String(order.memberId || '').trim();
var candidates = [ids.userId, ids.docId, ids.authUid].filter(Boolean).map(String);
for (var i = 0; i < candidates.length; i++) {
var c = candidates[i];
if (orderUser === c || orderMember === c) return true;
}
return false;
}
function getCurrentProductIdFromPage() {
try {
var params = new URLSearchParams(window.location.search);
var id = params.get('id') || '';
if (id) return String(id).trim();
} catch (e) { /* ignore */ }
try {
return String(sessionStorage.getItem('selectedProductId') || '').trim();
} catch (e2) {
return '';
}
}
function orderTimeMs(order) {
var t = order && (order.createdAt || order.approvedAt || order.updatedAt);
if (!t) return 0;
if (typeof t.toMillis === 'function') return t.toMillis();
if (t.seconds != null) return t.seconds * 1000;
var n = Number(t);
return isFinite(n) ? n : 0;
}
function normalizeProductId(value) {
return String(value == null ? '' : value).trim();
}
async function resolveMemberIds(user, authUser) {
var ids = {
userId: String((user && user.userId) || '').trim(),
docId: String((user && (user.docId || user.uid)) || '').trim(),
authUid: String((authUser && authUser.uid) || '').trim(),
};
if (ids.docId || !ids.userId || !firebase.firestore) return ids;
try {
var snap = await firebase
.firestore()
.collection('members')
.where('userId', '==', ids.userId)
.limit(1)
.get();
if (!snap.empty) {
ids.docId = snap.docs[0].id;
}
} catch (e) {
console.warn('[product-game-buttons] members 조회 실패:', e);
}
if (!ids.docId && ids.authUid) ids.docId = ids.authUid;
return ids;
}
function collectFromSnap(snap, ids, best) {
if (!snap || !snap.docs) return;
snap.docs.forEach(function (doc) {
var d = doc.data() || {};
var status = String(d.status || '').trim();
if (status !== 'approved') return;
if (d.lotteryCompleted === true) return;
if (!isOrderOwnedByUser(d, ids)) return;
var productId = normalizeProductId(d.productId);
if (!productId) return;
var row = {
orderId: doc.id,
productId: productId,
createdAtMs: orderTimeMs(d),
};
var prev = best[productId];
if (!prev || row.createdAtMs >= prev.createdAtMs) {
best[productId] = row;
}
});
}
async function loadPendingLotteryByProduct() {
if (!isLoggedIn()) return {};
var user = getLoginUser();
if (!user || !user.userId) return {};
var ready = await waitForFirebase();
if (!ready || !firebase.firestore) return {};
var authUser = await waitForAuthUser(4000);
var ids = await resolveMemberIds(user, authUser);
var db = firebase.firestore();
var best = {};
var queries = [];
// 본인 주문만 조회 (전체 approved limit은 본인 주문이 빠질 수 있음)
if (ids.userId) {
queries.push(
db.collection('orders').where('userId', '==', ids.userId).limit(100).get()
);
}
if (ids.docId && ids.docId !== ids.userId) {
queries.push(
db.collection('orders').where('memberId', '==', ids.docId).limit(100).get()
);
}
if (ids.authUid && ids.authUid !== ids.docId && ids.authUid !== ids.userId) {
queries.push(
db.collection('orders').where('memberId', '==', ids.authUid).limit(100).get()
);
queries.push(
db.collection('orders').where('userId', '==', ids.authUid).limit(100).get()
);
}
if (queries.length === 0) return {};
try {
var results = await Promise.all(
queries.map(function (p) {
return p.catch(function (err) {
console.warn('[product-game-buttons] 주문 조회 실패:', err);
return null;
});
})
);
results.forEach(function (snap) {
collectFromSnap(snap, ids, best);
});
mapLoadedOk = true;
return best;
} catch (e) {
console.warn('[product-game-buttons] 추첨 대기 주문 조회 실패:', e);
mapLoadedOk = false;
return {};
}
}
function ensurePendingMap(forceReload) {
if (!forceReload && pendingByProduct && mapLoadedOk) {
return Promise.resolve(pendingByProduct);
}
if (!forceReload && loadPromise) return loadPromise;
loadPromise = loadPendingLotteryByProduct().then(function (map) {
pendingByProduct = map || {};
loadPromise = null;
return pendingByProduct;
});
return loadPromise;
}
function setBuyButtonLotteryState(btn, orderInfo, defaultLabelHtml) {
if (!btn) return;
if (orderInfo && orderInfo.orderId) {
btn.setAttribute('data-lottery-order-id', orderInfo.orderId);
if (orderInfo.productId) {
btn.setAttribute('data-product-id', orderInfo.productId);
}
btn.classList.add('is-lottery-ready');
if (btn.classList.contains('btn-buy') || btn.classList.contains('btn-buy-fixed')) {
btn.innerHTML = ' 추첨하기';
} else {
btn.textContent = '추첨하기';
}
} else {
btn.removeAttribute('data-lottery-order-id');
btn.classList.remove('is-lottery-ready');
if (defaultLabelHtml != null) {
if (btn.classList.contains('btn-product-buy')) {
btn.textContent = '구매하기';
} else {
btn.innerHTML = defaultLabelHtml;
}
} else if (
btn.classList.contains('btn-buy') ||
btn.classList.contains('btn-buy-fixed')
) {
btn.innerHTML = ' 바로구매';
} else {
btn.textContent = '구매하기';
}
}
}
function applyLotteryButtonLabels(map) {
map = map || {};
document.querySelectorAll('.btn-product-buy').forEach(function (btn) {
var productId = normalizeProductId(btn.getAttribute('data-product-id'));
setBuyButtonLotteryState(btn, map[productId] || null, '구매하기');
});
var pageProductId = getCurrentProductIdFromPage();
document.querySelectorAll('.btn-buy, .btn-buy-fixed').forEach(function (btn) {
var productId =
normalizeProductId(btn.getAttribute('data-product-id')) ||
pageProductId;
if (productId) btn.setAttribute('data-product-id', productId);
setBuyButtonLotteryState(
btn,
productId ? map[productId] || null : null,
' 바로구매'
);
});
}
function refreshLotteryButtons(forceReload) {
var force = !!forceReload;
if (force) {
pendingByProduct = null;
loadPromise = null;
mapLoadedOk = false;
}
return ensurePendingMap(force).then(function (map) {
applyLotteryButtonLabels(map);
return map;
});
}
function scheduleRefresh(forceReload) {
if (applyTimer) clearTimeout(applyTimer);
applyTimer = setTimeout(function () {
refreshLotteryButtons(!!forceReload);
}, 120);
}
document.addEventListener(
'click',
function (e) {
var playBtn = e.target.closest && e.target.closest('.btn-product-game');
if (playBtn) {
e.preventDefault();
e.stopPropagation();
goLottery(playBtn.getAttribute('data-product-id'), 'game');
return;
}
var lotteryBtn =
e.target.closest &&
e.target.closest(
'.btn-product-buy.is-lottery-ready, .btn-buy.is-lottery-ready, .btn-buy-fixed.is-lottery-ready'
);
if (lotteryBtn) {
e.preventDefault();
e.stopPropagation();
goPurchaseLottery(
lotteryBtn.getAttribute('data-lottery-order-id'),
lotteryBtn.getAttribute('data-product-id') ||
getCurrentProductIdFromPage()
);
return;
}
var buyBtn = e.target.closest && e.target.closest('.btn-product-buy');
if (buyBtn) {
e.preventDefault();
e.stopPropagation();
goProductDetail(buyBtn.getAttribute('data-product-id'));
}
},
true
);
function boot() {
scheduleRefresh(true);
setTimeout(function () {
scheduleRefresh(true);
}, 1000);
setTimeout(function () {
scheduleRefresh(true);
}, 3000);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot);
} else {
boot();
}
window.ProductGameButtons = {
refresh: function (forceReload) {
return refreshLotteryButtons(forceReload !== false);
},
};
})();