| |
| |
| |
|
|
| import { Auth } from '../auth/Auth.js'; |
|
|
| export class AuthUI { |
| constructor({ onEnter, adminOnly = false } = {}) { |
| this.onEnter = onEnter; |
| this.adminOnly = adminOnly; |
| this.mode = 'login'; |
| this._bind(); |
| if (this.adminOnly) this._applyAdminMode(); |
| this.setMode('login'); |
| } |
|
|
| |
| _applyAdminMode() { |
| const tabReg = this.$('tabRegister'); |
| if (tabReg) tabReg.style.display = 'none'; |
| const tabLogin = this.$('tabLogin'); |
| if (tabLogin) tabLogin.textContent = 'Admin sign-in'; |
| const guestRow = document.querySelector('.auth-card .guest'); |
| if (guestRow) guestRow.style.display = 'none'; |
| |
| const h2 = document.querySelector('.auth-card h2'); |
| if (h2) h2.textContent = 'ECHO · Admin'; |
| const sub = this.$('authSub'); |
| if (sub) sub.textContent = 'Restricted area. Admin credentials required.'; |
| } |
|
|
| $(id) { return document.getElementById(id); } |
|
|
| _bind() { |
| this.$('tabLogin').addEventListener('click', () => this.setMode('login')); |
| this.$('tabRegister').addEventListener('click', () => this.setMode('register')); |
| |
| this.$('authForm').addEventListener('submit', e => this._submit(e)); |
| |
| this.$('authBtn').addEventListener('click', e => { e.preventDefault(); this._submit(e); }); |
| this.$('forgotBtn').addEventListener('click', () => this._forgot()); |
| this.$('guestBtn').addEventListener('click', () => { Auth.logout().catch(()=>{});this.hide(); this.onEnter?.(true); }); |
| this.$('signOutBtn').addEventListener('click', () => { Auth.logout().catch(()=>{});location.reload(); }); |
| console.log('[Auth] UI bound successfully'); |
| } |
|
|
| setMode(m) { |
| |
| if (this.adminOnly) m = 'login'; |
| this.mode = m; |
| this.$('tabLogin').classList.toggle('active', m === 'login'); |
| this.$('tabRegister').classList.toggle('active', m === 'register'); |
| this.$('fNameRow').style.display = m === 'register' ? 'block' : 'none'; |
| this.$('fPwd2Row').style.display = m === 'register' ? 'block' : 'none'; |
| this.$('authBtn').textContent = m === 'login' ? 'Login' : 'Create account'; |
| if (!this.adminOnly) { |
| this.$('authSub').textContent = m === 'login' |
| ? 'Welcome back — sign in to resume.' |
| : 'Create an account — track stars, climb the leaderboard.'; |
| } |
| this.$('forgotBtn').style.display = (m === 'login' && !this.adminOnly) ? 'inline' : 'none'; |
| this.$('fErr').textContent = ''; |
| } |
|
|
| async _submit(e) { |
| if (e?.preventDefault) e.preventDefault(); |
| const email = this.$('fEmail').value; |
| const pwd = this.$('fPwd').value; |
| const pwd2 = this.$('fPwd2').value; |
| const name = this.$('fName').value; |
| console.log(`[Auth] ${this.mode} submit: email="${email}" pwd.len=${pwd.length}`); |
|
|
| if (!email) { |
| this.$('fErr').style.color = 'var(--coral)'; |
| this.$('fErr').textContent = 'Email is required.'; |
| return; |
| } |
| if (!pwd) { |
| this.$('fErr').style.color = 'var(--coral)'; |
| this.$('fErr').textContent = 'Password is required.'; |
| return; |
| } |
|
|
| try { |
| let user; |
| if (this.mode === 'register') { |
| if (this.adminOnly) throw new Error('Registration is closed on /admin'); |
| if (pwd !== pwd2) throw new Error('Passwords do not match'); |
| user = await Auth.register(email, pwd, name); |
| console.log('[Auth] registered:', user.email); |
| } else { |
| user = await Auth.login(email, pwd); |
| console.log('[Auth] logged in:', user.email); |
| } |
| |
| if (this.adminOnly && !user.isAdmin) { |
| await Auth.logout().catch(() => {}); |
| throw new Error('Admin access only.'); |
| } |
| this.$('fErr').style.color = 'var(--spring)'; |
| this.$('fErr').textContent = `✓ Welcome, ${user.name}!`; |
| setTimeout(() => { |
| this.hide(); |
| this.onEnter?.(false); |
| }, 350); |
| } catch (err) { |
| console.warn('[Auth] error:', err.message); |
| this.$('fErr').style.color = 'var(--coral)'; |
| this.$('fErr').textContent = err.message; |
| } |
| } |
|
|
| _forgot() { |
| const email = this.$('fEmail').value.trim(); |
| if (!email) { this.$('fErr').textContent = 'Type your email above, then click Forgot password.'; return; } |
| const np = prompt(`Enter a new password (6+ chars) for ${email}:`); |
| if (!np) return; |
| try { |
| Auth.resetPwd(email, np); |
| this.$('fErr').style.color = 'var(--spring)'; |
| this.$('fErr').textContent = 'Password reset — login with the new one.'; |
| } catch (err) { |
| this.$('fErr').style.color = 'var(--coral)'; |
| this.$('fErr').textContent = err.message; |
| } |
| } |
|
|
| show() { this.$('authScreen').classList.remove('hidden'); this.$('appWrap').style.display = 'none'; } |
| hide() { this.$('authScreen').classList.add('hidden'); this.$('appWrap').style.display = ''; } |
| } |
|
|