Ctrl K
ComunidadGuías…

public/reset.html

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ham Radio Control — Reset hasła</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tabler-icons/2.47.0/iconfont/tabler-icons.min.css">
<style>
:root {
  /* Paleta "SDR Studio Pro" (przejeta z forka 2026-10-16, patrz style.css) */
  --bg:     #070b14; --panel: #0d1424; --panel2: #131c31;
  --border: rgba(56,189,248,0.14); --border2: rgba(56,189,248,0.30);
  --green:  #38bdf8; --green2: #0284c7; --dim: rgba(148,163,184,0.65);
  --green-rgb: 56,189,248; --amber-rgb: 251,191,36; --red-rgb: 244,63,94;
  --text:   #f1f5f9; --red: #f43f5e; --amber: #fbbf24;
  --mono: 'JetBrains Mono', 'Share Tech Mono', monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
  height: 100%; background: var(--bg); color: var(--text);
  font-family: var(--mono); display: flex; align-items: center; justify-content: center;
}
.card {
  background: var(--panel); border: 1px solid var(--border2); border-radius: 8px;
  padding: 36px 40px; width: 100%; max-width: 400px; text-align: center;
}
.logo { font-size: 12px; color: var(--dim); letter-spacing: 3px; margin-bottom: 24px; }
.logo-accent { color: var(--green); }
h2 { font-size: 16px; color: var(--text); letter-spacing: 2px; margin-bottom: 8px; font-weight: 400; }
.sub { font-size: 10px; color: var(--dim); line-height: 1.8; margin-bottom: 24px; }
.field { margin-bottom: 14px; text-align: left; }
.field label { display: block; font-size: 9px; color: var(--dim); letter-spacing: 1px; margin-bottom: 5px; }
.field input {
  width: 100%; background: var(--panel2); border: 1px solid var(--border2);
  border-radius: 4px; color: var(--text); font-family: var(--mono);
  font-size: 13px; padding: 10px 12px; outline: none;
}
.field input:focus { border-color: var(--green); }
.btn {
  width: 100%; background: rgba(var(--green-rgb),0.12); border: 1px solid var(--green2);
  border-radius: 5px; color: var(--green); font-family: var(--mono); font-size: 12px;
  padding: 13px; cursor: pointer; letter-spacing: 1px; margin-top: 6px;
  transition: all 0.15s;
}
.btn:hover { background: rgba(var(--green-rgb),0.22); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.msg { font-size: 11px; margin-top: 14px; padding: 10px; border-radius: 4px;
       min-height: 36px; line-height: 1.7; }
.msg.ok  { color: var(--green); background: rgba(var(--green-rgb),0.08); border: 1px solid var(--border); }
.msg.err { color: var(--red);   background: rgba(var(--red-rgb),0.08); border: 1px solid rgba(var(--red-rgb),0.25); }
.link { font-size: 10px; color: var(--dim); margin-top: 20px; }
.link a { color: var(--green); text-decoration: none; }
.link a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div class="card">
  <div class="logo">HAM RADIO <span class="logo-accent">CTRL</span></div>

  <!-- KROK 1: prośba o reset (gdy brak tokenu w URL) -->
  <div id="step-request">
    <h2>RESET HASŁA</h2>
    <div class="sub">Wpisz swój email lub nazwę użytkownika.<br>Wyślemy link resetujący ważny przez 1 godzinę.</div>
    <div class="field">
      <label>EMAIL LUB NAZWA UŻYTKOWNIKA</label>
      <input type="text" id="req-email" placeholder="twoj@email.com" autocomplete="email"
             onkeydown="if(event.key==='Enter') sendRequest()">
    </div>
    <button class="btn" id="req-btn" onclick="sendRequest()">WYŚLIJ LINK RESETUJĄCY</button>
    <div id="req-msg" class="msg" style="display:none;"></div>
    <div class="link"><a href="/login.html">← Wróć do logowania</a></div>
  </div>

  <!-- KROK 2: ustawienie nowego hasła (gdy token w URL) -->
  <div id="step-confirm" style="display:none;">
    <h2>NOWE HASŁO</h2>
    <div class="sub">Wpisz i potwierdź nowe hasło.<br>Minimum 6 znaków.</div>
    <div class="field">
      <label>NOWE HASŁO</label>
      <input type="password" id="new-pw" placeholder="••••••••" autocomplete="new-password"
             onkeydown="if(event.key==='Enter') confirmReset()">
    </div>
    <div class="field">
      <label>POWTÓRZ HASŁO</label>
      <input type="password" id="new-pw2" placeholder="••••••••" autocomplete="new-password"
             onkeydown="if(event.key==='Enter') confirmReset()">
    </div>
    <button class="btn" id="conf-btn" onclick="confirmReset()">ZAPISZ NOWE HASŁO</button>
    <div id="conf-msg" class="msg" style="display:none;"></div>
    <div class="link"><a href="/login.html">← Wróć do logowania</a></div>
  </div>

  <!-- KROK 3: sukces -->
  <div id="step-done" style="display:none;">
    <h2>✓ HASŁO ZMIENIONE</h2>
    <div class="sub" style="margin-top:12px;">
      Twoje hasło zostało zmienione.<br>Możesz teraz się zalogować.
    </div>
    <a href="/login.html"><button class="btn" style="margin-top:20px;">ZALOGUJ SIĘ</button></a>
  </div>
</div>

<script>
// Sprawdź czy mamy token w URL → krok 2
const _token = new URLSearchParams(location.search).get('token');
if (_token) {
  document.getElementById('step-request').style.display = 'none';
  document.getElementById('step-confirm').style.display = '';
}

function _msg(elId, text, type) {
  const el = document.getElementById(elId);
  el.style.display = '';
  el.textContent   = text;
  el.className     = 'msg ' + type;
}

// ── Krok 1: wyślij prośbę ────────────────────────────────────────────────────
async function sendRequest() {
  const email = document.getElementById('req-email').value.trim();
  if (!email) { _msg('req-msg', 'Wpisz email lub nazwę użytkownika', 'err'); return; }
  const btn = document.getElementById('req-btn');
  btn.disabled = true;
  btn.textContent = 'Wysyłam…';
  try {
    const r = await fetch('/api/auth/reset-request', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email,
        base_url: location.origin,
      }),
    });
    const data = await r.json();
    _msg('req-msg',
      '✓ Jeśli konto istnieje i ma przypisany email — link resetujący został wysłany. ' +
      'Sprawdź skrzynkę (i folder SPAM).',
      'ok');
  } catch(e) {
    _msg('req-msg', '✗ Błąd serwera — spróbuj ponownie', 'err');
  }
  btn.disabled = false;
  btn.textContent = 'WYŚLIJ LINK RESETUJĄCY';
}

// ── Krok 2: ustaw nowe hasło ─────────────────────────────────────────────────
async function confirmReset() {
  const pw  = document.getElementById('new-pw').value;
  const pw2 = document.getElementById('new-pw2').value;
  if (!pw || pw.length < 6) {
    _msg('conf-msg', 'Hasło musi mieć minimum 6 znaków', 'err'); return;
  }
  if (pw !== pw2) {
    _msg('conf-msg', 'Hasła nie są identyczne', 'err'); return;
  }
  const btn = document.getElementById('conf-btn');
  btn.disabled = true;
  btn.textContent = 'Zapisuję…';
  try {
    const r = await fetch('/api/auth/reset-confirm', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token: _token, password: pw }),
    });
    const data = await r.json();
    if (data.ok) {
      document.getElementById('step-confirm').style.display = 'none';
      document.getElementById('step-done').style.display = '';
    } else {
      _msg('conf-msg', '✗ ' + (data.error || 'Błąd'), 'err');
      btn.disabled = false;
      btn.textContent = 'ZAPISZ NOWE HASŁO';
    }
  } catch(e) {
    _msg('conf-msg', '✗ Błąd serwera', 'err');
    btn.disabled = false;
    btn.textContent = 'ZAPISZ NOWE HASŁO';
  }
}
</script>
</body>
</html>