Initial commit: SREBOT website (Express/EJS + i18n) - extracted from SREBOT monorepo
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const modal = document.getElementById('season-recap-modal');
|
||||
const btn = document.getElementById('season-recap-btn');
|
||||
const selectEl = document.getElementById('season-recap-select');
|
||||
const genBtn = document.getElementById('season-recap-generate');
|
||||
const img = document.getElementById('season-recap-image');
|
||||
const statusEl = document.getElementById('season-recap-status');
|
||||
|
||||
if (!modal || !btn || !selectEl || !genBtn || !img) {
|
||||
console.warn('[recap] modal elements not found; skipping init');
|
||||
return;
|
||||
}
|
||||
|
||||
const scriptTag = document.currentScript;
|
||||
const clanId = scriptTag && scriptTag.dataset.clanId;
|
||||
if (!clanId) {
|
||||
console.warn('[recap] no clan_id on script tag; disabling button');
|
||||
btn.disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
modal.classList.remove('hidden');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
function closeModal() {
|
||||
modal.classList.add('hidden');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
modal.querySelectorAll('[data-close]').forEach(el => el.addEventListener('click', closeModal));
|
||||
btn.addEventListener('click', async () => {
|
||||
openModal();
|
||||
if (!selectEl.options.length) await loadSeasons();
|
||||
});
|
||||
|
||||
function t(key) {
|
||||
return (window.__t && window.__t('seasonCard.' + key)) || key;
|
||||
}
|
||||
|
||||
async function loadSeasons() {
|
||||
statusEl.textContent = t('loadingSeasons');
|
||||
try {
|
||||
if (!window.apiClient) {
|
||||
throw new Error('apiClient not available');
|
||||
}
|
||||
const seasons = await window.apiClient.request('/api/seasons');
|
||||
const entries = Object.entries(seasons).sort((a, b) => b[1].start - a[1].start);
|
||||
selectEl.innerHTML = '';
|
||||
for (const [name, range] of entries) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = name;
|
||||
opt.textContent = range.status === 'in_progress'
|
||||
? `${name} ${t('inProgressSuffix')}`
|
||||
: name;
|
||||
selectEl.appendChild(opt);
|
||||
}
|
||||
statusEl.textContent = '';
|
||||
} catch (err) {
|
||||
console.error('[recap] seasons fetch failed:', err);
|
||||
statusEl.textContent = t('failedSeasons');
|
||||
}
|
||||
}
|
||||
|
||||
function selectedTheme() {
|
||||
const checked = document.querySelector('input[name="season-recap-theme"]:checked');
|
||||
return (checked && checked.value) || 'dark';
|
||||
}
|
||||
|
||||
genBtn.addEventListener('click', () => {
|
||||
const season = selectEl.value;
|
||||
if (!season) return;
|
||||
const theme = selectedTheme();
|
||||
const lang = document.documentElement.lang || 'en';
|
||||
const base = `/squadron/${encodeURIComponent(clanId)}/recap/${encodeURIComponent(season)}.png`;
|
||||
const params = new URLSearchParams({ theme, lang });
|
||||
statusEl.textContent = t('generating');
|
||||
img.style.display = 'none';
|
||||
img.onload = () => {
|
||||
statusEl.textContent = '';
|
||||
img.style.display = 'block';
|
||||
};
|
||||
img.onerror = () => {
|
||||
statusEl.textContent = t('failedGenerate');
|
||||
};
|
||||
const currentOpt = selectEl.options[selectEl.selectedIndex];
|
||||
const inProgressLabel = t('inProgressSuffix');
|
||||
const isInProgress = !!(currentOpt && inProgressLabel && currentOpt.textContent.indexOf(inProgressLabel) !== -1);
|
||||
if (isInProgress) params.set('t', String(Date.now()));
|
||||
img.src = `${base}?${params.toString()}`;
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user