feat(auth): Separate Login, Register, and Profile views with robust validations and SQL-safe backend
This commit is contained in:
1 parent
5f3abba27c
commit
4e450d758b
5 files changed
+392
-126
No files matched your search
+138
-44
@@ -206,7 +206,8 @@ window.GameEngine = class GameEngine {
|
||||
const btnAuth = document.getElementById('btn-auth-open');
|
||||
const btnLogoutNav = document.getElementById('btn-auth-logout-nav');
|
||||
const loggedInView = document.getElementById('auth-logged-in-view');
|
||||
const guestView = document.getElementById('auth-guest-view');
|
||||
const loginView = document.getElementById('auth-login-view') || document.getElementById('auth-guest-view');
|
||||
const registerView = document.getElementById('auth-register-view');
|
||||
const userTitle = document.getElementById('profile-user-title');
|
||||
const statCoins = document.getElementById('profile-stat-coins');
|
||||
const statLevel = document.getElementById('profile-stat-level');
|
||||
@@ -226,13 +227,15 @@ window.GameEngine = class GameEngine {
|
||||
else btnLogoutNav.classList.remove('hidden');
|
||||
}
|
||||
|
||||
if (loggedInView && guestView) {
|
||||
if (loggedInView) {
|
||||
if (isGuest) {
|
||||
loggedInView.classList.add('hidden');
|
||||
guestView.classList.remove('hidden');
|
||||
if (loginView) loginView.classList.remove('hidden');
|
||||
if (registerView) registerView.classList.add('hidden');
|
||||
} else {
|
||||
loggedInView.classList.remove('hidden');
|
||||
guestView.classList.add('hidden');
|
||||
if (loginView) loginView.classList.add('hidden');
|
||||
if (registerView) registerView.classList.add('hidden');
|
||||
|
||||
if (userTitle) userTitle.textContent = user;
|
||||
if (statCoins) statCoins.textContent = (uData.coins || (this.economy ? this.economy.totalCoins : 0)).toLocaleString('ru-RU');
|
||||
@@ -897,14 +900,37 @@ window.GameEngine = class GameEngine {
|
||||
const btnAuthOpen = document.getElementById('btn-auth-open');
|
||||
const btnAuthClose = document.getElementById('btn-auth-close');
|
||||
const btnAuthCloseProfile = document.getElementById('btn-auth-close-profile');
|
||||
const btnAuthSubmit = document.getElementById('btn-auth-submit');
|
||||
const btnAuthGuest = document.getElementById('btn-auth-guest');
|
||||
const btnAuthLogout = document.getElementById('btn-auth-logout');
|
||||
const btnAuthCloseReg = document.getElementById('btn-auth-close-reg');
|
||||
|
||||
const loginView = document.getElementById('auth-login-view') || document.getElementById('auth-guest-view');
|
||||
const registerView = document.getElementById('auth-register-view');
|
||||
|
||||
const btnAuthToRegister = document.getElementById('btn-auth-to-register');
|
||||
const btnAuthToLogin = document.getElementById('btn-auth-to-login');
|
||||
|
||||
const btnAuthSubmit = document.getElementById('btn-auth-submit'); // Войти
|
||||
const btnAuthDoRegister = document.getElementById('btn-auth-do-register'); // Зарегистрироваться
|
||||
const btnAuthGuest = document.getElementById('btn-auth-guest'); // Остаться гостем
|
||||
const btnAuthLogout = document.getElementById('btn-auth-logout'); // Выйти
|
||||
const btnAuthLogoutNav = document.getElementById('btn-auth-logout-nav');
|
||||
|
||||
const authUser = document.getElementById('auth-username');
|
||||
const authPass = document.getElementById('auth-password');
|
||||
const authError = document.getElementById('auth-error');
|
||||
|
||||
const authRegUser = document.getElementById('auth-reg-username');
|
||||
const authRegPass = document.getElementById('auth-reg-password');
|
||||
const authRegError = document.getElementById('auth-reg-error');
|
||||
|
||||
const resetAuthForms = () => {
|
||||
if (authUser) authUser.value = '';
|
||||
if (authPass) authPass.value = '';
|
||||
if (authError) { authError.textContent = ''; authError.classList.add('hidden'); }
|
||||
if (authRegUser) authRegUser.value = '';
|
||||
if (authRegPass) authRegPass.value = '';
|
||||
if (authRegError) { authRegError.textContent = ''; authRegError.classList.add('hidden'); }
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
if (window.PvZAuth) {
|
||||
window.PvZAuth.logout();
|
||||
@@ -914,9 +940,7 @@ window.GameEngine = class GameEngine {
|
||||
this.updateShopUI();
|
||||
}
|
||||
if (authModal) authModal.classList.add('hidden');
|
||||
if (authUser) authUser.value = '';
|
||||
if (authPass) authPass.value = '';
|
||||
if (authError) authError.classList.add('hidden');
|
||||
resetAuthForms();
|
||||
if (window.PvZAudio) window.PvZAudio.playCoin();
|
||||
};
|
||||
|
||||
@@ -929,15 +953,20 @@ window.GameEngine = class GameEngine {
|
||||
|
||||
if (btnAuthOpen && authModal) {
|
||||
btnAuthOpen.addEventListener('click', () => {
|
||||
if (authError) authError.classList.add('hidden');
|
||||
resetAuthForms();
|
||||
this.updateProfileUI();
|
||||
authModal.classList.remove('hidden');
|
||||
if (authUser && window.PvZAuth && window.PvZAuth.isGuest()) authUser.focus();
|
||||
if (authUser && window.PvZAuth && window.PvZAuth.isGuest()) {
|
||||
setTimeout(() => authUser.focus(), 50);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Modal Close buttons
|
||||
if (btnAuthClose && authModal) {
|
||||
btnAuthClose.addEventListener('click', () => {
|
||||
authModal.classList.add('hidden');
|
||||
resetAuthForms();
|
||||
});
|
||||
}
|
||||
if (btnAuthCloseProfile && authModal) {
|
||||
@@ -945,61 +974,80 @@ window.GameEngine = class GameEngine {
|
||||
authModal.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
if (btnAuthGuest && authModal) {
|
||||
btnAuthGuest.addEventListener('click', () => {
|
||||
handleLogout();
|
||||
if (btnAuthCloseReg && authModal) {
|
||||
btnAuthCloseReg.addEventListener('click', () => {
|
||||
authModal.classList.add('hidden');
|
||||
resetAuthForms();
|
||||
});
|
||||
}
|
||||
|
||||
// Switch between Login and Register views
|
||||
if (btnAuthToRegister && loginView && registerView) {
|
||||
btnAuthToRegister.addEventListener('click', () => {
|
||||
resetAuthForms();
|
||||
loginView.classList.add('hidden');
|
||||
registerView.classList.remove('hidden');
|
||||
if (authRegUser) setTimeout(() => authRegUser.focus(), 50);
|
||||
});
|
||||
}
|
||||
|
||||
if (btnAuthToLogin && loginView && registerView) {
|
||||
btnAuthToLogin.addEventListener('click', () => {
|
||||
resetAuthForms();
|
||||
registerView.classList.add('hidden');
|
||||
loginView.classList.remove('hidden');
|
||||
if (authUser) setTimeout(() => authUser.focus(), 50);
|
||||
});
|
||||
}
|
||||
|
||||
// Stay as Guest button
|
||||
if (btnAuthGuest && authModal) {
|
||||
btnAuthGuest.addEventListener('click', () => {
|
||||
if (window.PvZAuth) window.PvZAuth.loginAsGuest();
|
||||
this.loadUserData();
|
||||
this.updateProfileUI();
|
||||
this.updateRecordDisplay();
|
||||
authModal.classList.add('hidden');
|
||||
resetAuthForms();
|
||||
if (window.PvZAudio) window.PvZAudio.playButtonClick();
|
||||
});
|
||||
}
|
||||
|
||||
// Login Action (Войти)
|
||||
if (btnAuthSubmit && authModal) {
|
||||
btnAuthSubmit.addEventListener('click', () => {
|
||||
btnAuthSubmit.addEventListener('click', async () => {
|
||||
const u = authUser ? authUser.value.trim() : '';
|
||||
const p = authPass ? authPass.value : '';
|
||||
|
||||
if (!u) {
|
||||
if (authError) { authError.textContent = 'Введите имя пользователя'; authError.classList.remove('hidden'); }
|
||||
if (authError) { authError.textContent = 'Введите логин'; authError.classList.remove('hidden'); }
|
||||
return;
|
||||
}
|
||||
if (!p && u.toLowerCase() !== 'гость') {
|
||||
if (!p) {
|
||||
if (authError) { authError.textContent = 'Введите пароль'; authError.classList.remove('hidden'); }
|
||||
return;
|
||||
}
|
||||
if (authError) authError.classList.add('hidden');
|
||||
|
||||
if (window.PvZAuth) {
|
||||
btnAuthSubmit.textContent = '⏳ Подключение...';
|
||||
btnAuthSubmit.textContent = '⏳ Вход...';
|
||||
btnAuthSubmit.disabled = true;
|
||||
|
||||
const res = window.PvZAuth.login(u, p, (serverData, errMsg) => {
|
||||
// Server response callback (async)
|
||||
btnAuthSubmit.textContent = 'Войти / Регистрация';
|
||||
btnAuthSubmit.disabled = false;
|
||||
if (errMsg) {
|
||||
// Wrong password from server
|
||||
if (authError) { authError.textContent = errMsg; authError.classList.remove('hidden'); }
|
||||
// Restore guest state in UI
|
||||
this.updateProfileUI();
|
||||
return;
|
||||
}
|
||||
if (serverData) {
|
||||
this.loadUserData();
|
||||
this.updateProfileUI();
|
||||
this.updateRecordDisplay();
|
||||
this.updateShopUI();
|
||||
}
|
||||
});
|
||||
const res = await window.PvZAuth.login(u, p);
|
||||
btnAuthSubmit.textContent = '🔑 Войти';
|
||||
btnAuthSubmit.disabled = false;
|
||||
|
||||
if (res.success) {
|
||||
// Optimistic: close modal immediately (data loads async)
|
||||
if (res && res.success) {
|
||||
authModal.classList.add('hidden');
|
||||
if (authUser) authUser.value = '';
|
||||
if (authPass) authPass.value = '';
|
||||
resetAuthForms();
|
||||
this.loadUserData();
|
||||
this.updateProfileUI();
|
||||
this.updateRecordDisplay();
|
||||
this.updateShopUI();
|
||||
if (window.PvZAudio) window.PvZAudio.playCoin();
|
||||
} else {
|
||||
btnAuthSubmit.textContent = 'Войти / Регистрация';
|
||||
btnAuthSubmit.disabled = false;
|
||||
if (authError) {
|
||||
authError.textContent = res.message || 'Ошибка входа';
|
||||
authError.textContent = (res && res.message) ? res.message : 'Неверный логин или пароль';
|
||||
authError.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
@@ -1007,6 +1055,52 @@ window.GameEngine = class GameEngine {
|
||||
});
|
||||
}
|
||||
|
||||
// Register Action (Зарегистрироваться)
|
||||
if (btnAuthDoRegister && authModal) {
|
||||
btnAuthDoRegister.addEventListener('click', async () => {
|
||||
const u = authRegUser ? authRegUser.value.trim() : '';
|
||||
const p = authRegPass ? authRegPass.value : '';
|
||||
|
||||
if (!u) {
|
||||
if (authRegError) { authRegError.textContent = 'Введите логин для регистрации'; authRegError.classList.remove('hidden'); }
|
||||
return;
|
||||
}
|
||||
if (u.length < 3) {
|
||||
if (authRegError) { authRegError.textContent = 'Логин должен содержать минимум 3 символа'; authRegError.classList.remove('hidden'); }
|
||||
return;
|
||||
}
|
||||
if (!p || p.length < 4) {
|
||||
if (authRegError) { authRegError.textContent = 'Пароль должен содержать минимум 4 символа'; authRegError.classList.remove('hidden'); }
|
||||
return;
|
||||
}
|
||||
if (authRegError) authRegError.classList.add('hidden');
|
||||
|
||||
if (window.PvZAuth) {
|
||||
btnAuthDoRegister.textContent = '⏳ Регистрация...';
|
||||
btnAuthDoRegister.disabled = true;
|
||||
|
||||
const res = await window.PvZAuth.register(u, p);
|
||||
btnAuthDoRegister.textContent = '✨ Зарегистрироваться';
|
||||
btnAuthDoRegister.disabled = false;
|
||||
|
||||
if (res && res.success) {
|
||||
authModal.classList.add('hidden');
|
||||
resetAuthForms();
|
||||
this.loadUserData();
|
||||
this.updateProfileUI();
|
||||
this.updateRecordDisplay();
|
||||
this.updateShopUI();
|
||||
if (window.PvZAudio) window.PvZAudio.playCoin();
|
||||
} else {
|
||||
if (authRegError) {
|
||||
authRegError.textContent = (res && res.message) ? res.message : 'Ошибка при регистрации';
|
||||
authRegError.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Shop Button
|
||||
const btnShop = document.getElementById('btn-shop');
|
||||
|
||||
Reference in new issue
Block a user