wa-dev-tools/public/register.html
treamz 27ad078e07 Unified header: same top-header across landing, login, register, status
- Landing: replaced custom landing-nav with standard top-header
- Removed scroll listener for nav (no longer needed)
- Header CSS moved to shared.css (single source)
- Removed duplicate header CSS from login, register, status
- All 4 public pages now have identical header with theme toggle
2026-03-22 00:49:52 +03:00

136 lines
8.5 KiB
HTML

<!DOCTYPE html>
<html lang="ru" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Регистрация — WA Dev Tools</title>
<script src="/vendor/tailwind.js"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: { extend: {
fontFamily: { mono: ['JetBrains Mono', 'monospace'], sans: ['Manrope', 'sans-serif'] },
colors: { surface: { 900: '#060c18', 800: '#091020', 700: '#0d1828', 600: '#162040' }, accent: { DEFAULT: '#0054e6', dim: '#0043b8', bright: '#6b9fff' } }
}}
};
</script>
<link href="/vendor/fonts.css" rel="stylesheet">
<link href="/shared.css" rel="stylesheet">
<style>
/* Content */
.page-body { padding-top:56px; min-height:100vh; display:flex; align-items:center; justify-content:center; }
.auth-card { max-width:420px; width:100%; padding:20px; }
.auth-card-inner { background:var(--surface-700); border:1px solid var(--surface-600); border-radius:16px; padding:36px 32px; box-shadow:0 4px 24px rgba(0,0,0,.1); }
.auth-title { font-size:24px; font-weight:800; color:var(--text-primary); text-align:center; }
.auth-subtitle { font-size:14px; color:var(--text-muted); text-align:center; margin-top:6px; }
.auth-label { display:block; font-size:13px; color:var(--text-muted); margin-bottom:6px; font-family:'JetBrains Mono',monospace; font-weight:500; }
.auth-input { width:100%; background:var(--select-bg); border:1px solid var(--surface-600); color:var(--select-color); padding:12px 16px; border-radius:10px; font-family:'Manrope',sans-serif; font-size:15px; outline:none; transition:border-color .2s; }
.auth-input:focus { border-color:var(--accent); }
.auth-input::placeholder { color:var(--text-muted); opacity:.6; }
.auth-btn { width:100%; padding:14px; background:var(--accent); color:#fff; border:none; border-radius:10px; font-family:'Manrope',sans-serif; font-weight:700; font-size:16px; cursor:pointer; transition:background .2s; }
.auth-btn:hover { background:var(--accent-dim); }
.auth-btn:disabled { opacity:0.5; cursor:not-allowed; }
.auth-error { background:rgba(255,82,82,.08); border:1px solid rgba(255,82,82,.25); color:#ff5252; padding:10px 14px; border-radius:8px; font-size:13px; display:none; }
.auth-error.visible { display:block; }
.auth-footer { text-align:center; margin-top:20px; font-size:14px; color:var(--text-muted); }
.auth-footer a { color:var(--accent); text-decoration:none; font-weight:600; }
.auth-footer a:hover { text-decoration:underline; }
.auth-divider { height:1px; background:var(--surface-600); margin:20px 0; }
.auth-hint { font-size:11px; color:var(--text-muted); margin-top:4px; font-family:'JetBrains Mono',monospace; opacity:.7; }
</style>
<script>
(function(){
const s = localStorage.getItem('theme');
if (s === '' || (s === null && !window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.remove('dark');
}
})();
</script>
</head>
<body>
<header class="top-header">
<a href="/" class="top-logo">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:var(--accent)"><path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"/></svg>
WA Dev <span>Tools</span>
</a>
<nav class="top-nav">
<a href="/">Главная</a>
<a href="/#tools">Инструменты</a>
<a href="/#features">Возможности</a>
</nav>
<div class="top-right">
<button class="theme-btn" id="themeBtn" title="Переключить тему">
<svg class="sun-i" width="16" height="16" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"/></svg>
<svg class="moon-i" width="16" height="16" fill="currentColor" viewBox="0 0 20 20"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/></svg>
</button>
<a href="/auth/login" class="btn-ghost">Войти</a>
<a href="/auth/register" class="btn-primary-sm active">Регистрация</a>
</div>
</header>
<div class="page-body">
<div class="auth-card">
<div class="auth-card-inner">
<div class="auth-title">Создать аккаунт</div>
<div class="auth-subtitle">Бесплатный доступ ко всем инструментам</div>
<div id="error" class="auth-error" style="margin-top:20px;"></div>
<form id="regForm" style="display:flex;flex-direction:column;gap:16px;margin-top:24px;" onsubmit="return handleRegister(event)">
<div>
<label class="auth-label">Имя</label>
<input class="auth-input" type="text" name="name" placeholder="Как вас зовут" autocomplete="name" />
</div>
<div>
<label class="auth-label">Email</label>
<input class="auth-input" type="email" name="email" required autofocus autocomplete="email" placeholder="you@example.com" />
</div>
<div>
<label class="auth-label">Пароль</label>
<input class="auth-input" type="password" name="password" required minlength="6" autocomplete="new-password" placeholder="Придумайте пароль" />
<div class="auth-hint">минимум 6 символов</div>
</div>
<div>
<label class="auth-label">Подтвердите пароль</label>
<input class="auth-input" type="password" name="password2" required minlength="6" autocomplete="new-password" placeholder="Повторите пароль" />
</div>
<button class="auth-btn" type="submit" id="submitBtn">Зарегистрироваться</button>
</form>
<div class="auth-divider"></div>
<div class="auth-footer">Уже есть аккаунт? <a href="/auth/login">Войти</a></div>
</div>
</div>
</div>
<script>
const _tb = document.getElementById('themeBtn');
function _ut() {
const d = document.documentElement.classList.contains('dark');
document.querySelectorAll('.sun-i').forEach(e => e.style.display = d ? 'none' : 'block');
document.querySelectorAll('.moon-i').forEach(e => e.style.display = d ? 'block' : 'none');
}
_ut();
_tb.addEventListener('click', () => {
const d = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', d ? 'dark' : '');
_ut();
});
async function handleRegister(e) {
e.preventDefault();
const form = e.target, btn = document.getElementById('submitBtn'), err = document.getElementById('error');
err.classList.remove('visible');
if (form.password.value !== form.password2.value) { err.textContent = 'Пароли не совпадают'; err.classList.add('visible'); return; }
btn.disabled = true; btn.textContent = 'Регистрация...';
try {
const res = await fetch('/auth/register', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({name:form.name.value,email:form.email.value,password:form.password.value,password2:form.password2.value}) });
const data = await res.json();
if (data.ok) window.location.href = data.redirect || '/dashboard';
else { err.textContent = data.error; err.classList.add('visible'); }
} catch { err.textContent = 'Ошибка сети'; err.classList.add('visible'); }
btn.disabled = false; btn.textContent = 'Зарегистрироваться';
}
</script>
</body>
</html>