- Redesigned base.html: dark Minecraft theme, sticky header, responsive grid, cards, server cards with status indicators, profile styles - index.html: hero section, server list grid, how-to-start steps, features section - login.html: centered card layout, client-side validation, fetch API - registration.html: password confirmation, pattern validation, error alerts - profile.html: new page — skin/cape upload & delete, launcher download links, auth-gated via localStorage token - templates.go: added /profile route, extended pageData with Username/UUID
78 lines
3.3 KiB
HTML
78 lines
3.3 KiB
HTML
{{define "content"}}
|
||
<div class="container-narrow">
|
||
<div class="card text-center">
|
||
<h1 style="margin-bottom:0.5rem">🎮 Создать аккаунт</h1>
|
||
<p class="muted mb-0">Присоединяйся к MrixsCraft и начни играть.</p>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<div id="alert" class="alert alert-error"></div>
|
||
<form id="regForm" novalidate>
|
||
<label for="username">Никнейм</label>
|
||
<input type="text" id="username" name="username" required minlength="3" maxlength="20" autocomplete="username"
|
||
placeholder="Player" pattern="[a-zA-Z0-9_]{3,20}">
|
||
<p class="form-error" id="err-username">3–20 символов: латиница, цифры, _</p>
|
||
|
||
<label for="email">Email</label>
|
||
<input type="email" id="email" name="email" required autocomplete="email" placeholder="player@email.com">
|
||
|
||
<label for="password">Пароль</label>
|
||
<input type="password" id="password" name="password" required minlength="6" autocomplete="new-password" placeholder="Минимум 6 символов">
|
||
|
||
<label for="password2">Подтверждение пароля</label>
|
||
<input type="password" id="password2" name="password2" required autocomplete="new-password" placeholder="Повтори пароль">
|
||
<p class="form-error" id="err-password">Пароли не совпадают</p>
|
||
|
||
<button type="submit" class="btn" style="width:100%">Создать аккаунт</button>
|
||
</form>
|
||
<p class="text-center mt-2 muted">Уже есть аккаунт? <a href="/login">Войти</a></p>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.getElementById('regForm').addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
const alert = document.getElementById('alert');
|
||
alert.className = 'alert alert-error';
|
||
alert.classList.remove('show');
|
||
|
||
const username = document.getElementById('username').value.trim();
|
||
const email = document.getElementById('email').value.trim();
|
||
const password = document.getElementById('password').value;
|
||
const password2 = document.getElementById('password2').value;
|
||
|
||
// Client-side validation
|
||
if (!/^[a-zA-Z0-9_]{3,20}$/.test(username)) {
|
||
document.getElementById('err-username').style.display = 'block';
|
||
return;
|
||
}
|
||
document.getElementById('err-username').style.display = 'none';
|
||
|
||
if (password !== password2) {
|
||
document.getElementById('err-password').style.display = 'block';
|
||
return;
|
||
}
|
||
document.getElementById('err-password').style.display = 'none';
|
||
|
||
try {
|
||
const res = await fetch('/api/web/register', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({username, email, password})
|
||
});
|
||
const data = await res.json();
|
||
if (!res.ok) {
|
||
alert.textContent = data.error || 'Ошибка регистрации';
|
||
alert.classList.add('show');
|
||
return;
|
||
}
|
||
// Success — redirect to login
|
||
window.location.href = '/login';
|
||
} catch (err) {
|
||
alert.textContent = 'Ошибка сети. Попробуй ещё раз.';
|
||
alert.classList.add('show');
|
||
}
|
||
});
|
||
</script>
|
||
{{end}}
|