/* ClubLedger – main SPA */ let currentUser = null; let cashierMember = null; let barMember = null; let editMemberId = null; let editAccountId = null; // --------------------------------------------------------------------------- // Boot – check session, then either show login or start the app // --------------------------------------------------------------------------- (async function boot() { // Load config first so the login page shows the club name await loadConfig(); document.getElementById('loginBrand').textContent = cfg.club_name; let me = null; try { me = await apiFetch('/auth/me'); } catch (e) { /* not logged in */ } if (!me) { showLogin(); return; } currentUser = me; await startApp(); })(); function showLogin() { document.getElementById('loginOverlay').classList.remove('hidden'); document.getElementById('loginUsername').focus(); document.getElementById('loginForm').addEventListener('submit', doLogin, { once: true }); } async function doLogin(e) { e.preventDefault(); const username = document.getElementById('loginUsername').value.trim(); const password = document.getElementById('loginPassword').value; try { currentUser = await apiFetch('/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); document.getElementById('loginOverlay').classList.add('hidden'); await startApp(); } catch (err) { setMsg('loginMsg', err.message, 'err'); document.getElementById('loginForm').addEventListener('submit', doLogin, { once: true }); } } async function doLogout() { try { await fetch('/auth/logout', { method: 'POST' }); } catch (e) { /* ignore */ } currentUser = null; // Reset tab visibility for next login document.getElementById('adminTabBtn').classList.add('hidden'); document.querySelector('[data-view="cashier"]').classList.remove('hidden'); document.querySelector('[data-view="bar"]').classList.remove('hidden'); // Reset to members tab document.querySelectorAll('.nav-btn').forEach(b => b.classList.remove('active')); document.querySelector('[data-view="members"]').classList.add('active'); document.querySelectorAll('.view').forEach(v => v.classList.add('hidden')); document.getElementById('view-members').classList.remove('hidden'); showLogin(); } function populateTransferTypes() { const types = Array.isArray(cfg.transfer_types) ? cfg.transfer_types : []; ['cashierTransferType', 'withdrawalTransferType'].forEach(id => { const sel = document.getElementById(id); if (!sel) return; const prev = sel.value; sel.innerHTML = '' + types.map(t => ``).join(''); if (prev && types.includes(prev)) sel.value = prev; }); } function populateTimezoneList() { const list = document.getElementById('tz-list'); if (!list) return; try { list.innerHTML = Intl.supportedValuesOf('timeZone') .map(z => `