aipackage/cezen-portal/change-password.html
2026-06-30 10:51:41 +05:30

114 lines
5.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Change Password — Nexus One AI</title>
<link rel="stylesheet" href="style.css?v=4">
<style>
body { background:var(--navy); min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px; }
.cp-card { background:var(--navy2); border-radius:20px; padding:40px 44px; width:100%; max-width:420px; box-shadow:0 24px 64px rgba(0,0,0,.35); }
.cp-brand { font-size:22px; font-weight:800; color:var(--navy); margin-bottom:6px; }
.cp-brand span { color:var(--teal); }
.cp-headline { font-size:18px; font-weight:700; color:var(--ink); margin-bottom:6px; }
.cp-sub { font-size:13px; color:var(--lt); margin-bottom:28px; line-height:1.5; }
.cp-field { margin-bottom:16px; }
.cp-label { display:block; font-size:13px; font-weight:600; color:var(--med); margin-bottom:5px; }
.cp-input { width:100%; padding:11px 13px; border:1.5px solid var(--bdr); border-radius:9px; font-size:14px; font-family:inherit; color:var(--ink); outline:none; box-sizing:border-box; }
.cp-input:focus { border-color:var(--teal); }
.cp-err { background:rgba(185,28,28,.08); border:1px solid rgba(239,68,68,.25); color:#B91C1C; padding:9px 12px; border-radius:7px; font-size:12px; margin-bottom:14px; display:none; }
.cp-err.show { display:block; }
.cp-ok { background:rgba(34,197,94,.08); border:1px solid #86EFAC; color:#15803D; padding:9px 12px; border-radius:7px; font-size:12px; margin-bottom:14px; display:none; }
.cp-ok.show { display:block; }
.cp-btn { width:100%; padding:12px; background:var(--teal); color:var(--ink); border:none; border-radius:9px; font-size:15px; font-weight:700; cursor:pointer; font-family:inherit; margin-top:6px; transition:background .15s; }
.cp-btn:hover { background:#0B7A70; }
.cp-btn:disabled { opacity:.6; cursor:not-allowed; }
.cp-rules { font-size:11px; color:var(--lt); margin-top:10px; line-height:1.8; }
</style>
</head>
<body>
<div class="cp-card">
<div class="cp-brand">Nexus One <span>AI</span></div>
<div class="cp-headline">Set New Password</div>
<div class="cp-sub">Your password needs to be changed before you can continue. Choose a strong password you haven't used before.</div>
<div class="cp-err" id="cp-err"></div>
<div class="cp-ok" id="cp-ok">Password changed! Redirecting…</div>
<div class="cp-field">
<label class="cp-label">New Password</label>
<input class="cp-input" id="new-pw" type="password" placeholder="New password" autocomplete="new-password">
</div>
<div class="cp-field">
<label class="cp-label">Confirm Password</label>
<input class="cp-input" id="conf-pw" type="password" placeholder="Confirm new password" autocomplete="new-password">
</div>
<button class="cp-btn" id="cp-btn" onclick="doChange()">Change Password</button>
<div class="cp-rules">
✓ At least 8 characters &nbsp; ✓ Mix letters &amp; numbers
</div>
</div>
<script>
const API = '/api';
document.querySelectorAll('.cp-input').forEach(el => {
el.addEventListener('keydown', e => { if (e.key === 'Enter') doChange(); });
});
async function doChange() {
const errEl = document.getElementById('cp-err');
const okEl = document.getElementById('cp-ok');
const btn = document.getElementById('cp-btn');
errEl.classList.remove('show');
const np = document.getElementById('new-pw').value;
const cp = document.getElementById('conf-pw').value;
if (!np) { errEl.textContent = 'Enter a new password.'; errEl.classList.add('show'); return; }
if (np.length < 8) { errEl.textContent = 'Password must be at least 8 characters.'; errEl.classList.add('show'); return; }
if (np !== cp) { errEl.textContent = 'Passwords do not match.'; errEl.classList.add('show'); return; }
btn.disabled = true;
btn.textContent = 'Changing…';
try {
const res = await fetch(`${API}/auth/change-password`, {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ new_password: np })
});
if (res.ok) {
okEl.classList.add('show');
setTimeout(() => { window.location.href = '/index.html'; }, 1500);
} else {
const d = await res.json().catch(() => ({}));
const msg = Array.isArray(d.detail)
? d.detail.map(e => e.msg || JSON.stringify(e)).join(', ')
: (typeof d.detail === 'string' ? d.detail : 'Failed to change password.');
errEl.textContent = msg;
errEl.classList.add('show');
btn.disabled = false;
btn.textContent = 'Change Password';
}
} catch {
errEl.textContent = 'Network error. Try again.';
errEl.classList.add('show');
btn.disabled = false;
btn.textContent = 'Change Password';
}
}
// Verify user is logged in (don't redirect to login for change-password page)
fetch(`${API}/auth/me`, { credentials: 'include' }).then(r => {
if (!r.ok) window.location.href = '/login.html';
});
</script>
<script src="branding.js"></script>
</body>
</html>