Spaces:
Running
Running
File size: 6,954 Bytes
ba1e29d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | <!DOCTYPE html>
<html lang="sw">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="theme-color" content="#0e1116">
<meta name="robots" content="noindex">
<title>Weka Nenosiri Jipya — JAYNES MAX</title>
<style>
:root{--bg:#0e1116;--card:#161a21;--text:#f5f6f8;--muted:#9aa3af;--accent:#e50914;--accent2:#c7b8ff;--border:#242a33;}
*{box-sizing:border-box;margin:0;padding:0;}
html,body{height:100%;}
body{background:var(--bg);color:var(--text);font-family:-apple-system,Roboto,Segoe UI,Helvetica,Arial,sans-serif;
display:flex;align-items:center;justify-content:center;padding:20px;}
.card{width:100%;max-width:400px;background:var(--card);border:1px solid var(--border);border-radius:18px;padding:26px 22px;}
.brand{font-weight:800;font-size:18px;text-align:center;margin-bottom:6px;}
.brand span{color:var(--accent);}
h1{font-size:19px;text-align:center;margin-bottom:6px;}
.sub{font-size:13px;color:var(--muted);text-align:center;margin-bottom:20px;line-height:1.45;}
label{display:block;font-size:12px;color:var(--muted);margin:0 0 6px 2px;}
.field{position:relative;margin-bottom:14px;}
input{width:100%;padding:13px 44px 13px 14px;border-radius:12px;border:1px solid var(--border);
background:var(--bg);color:var(--text);font-size:15px;outline:none;}
input:focus{border-color:var(--accent2);}
.eye{position:absolute;right:6px;bottom:6px;width:36px;height:36px;border:none;background:none;color:var(--muted);font-size:17px;cursor:pointer;}
.track{height:4px;border-radius:999px;background:rgba(255,255,255,.08);overflow:hidden;margin:-6px 0 4px;}
.fill{height:100%;width:0;border-radius:999px;background:#ff5252;transition:width .25s,background .25s;}
.strength{font-size:11px;color:var(--muted);text-align:right;min-height:1.3em;margin-bottom:12px;}
.btn{width:100%;padding:13px;border:none;border-radius:999px;background:var(--accent2);color:#1b1230;
font-weight:700;font-size:15px;cursor:pointer;display:block;text-align:center;text-decoration:none;}
.btn:disabled{opacity:.55;cursor:default;}
.msg{font-size:13px;text-align:center;margin-top:14px;min-height:1.3em;line-height:1.4;}
.err{color:#ff8a80;} .ok{color:#5ee6a0;}
.big{font-size:44px;text-align:center;margin-bottom:10px;}
.hide{display:none;}
</style>
</head>
<body>
<div class="card">
<div class="brand">JAYNES <span>MAX</span></div>
<!-- Hali: kiungo kibaya / kimeisha muda -->
<div id="bad" class="hide">
<div class="big">⚠️</div>
<h1>Kiungo hakifanyi kazi</h1>
<p class="sub" id="badText">Kiungo hiki si sahihi au kimeisha muda. Omba kingine kupitia "Umesahau nenosiri?" kwenye app.</p>
<a class="btn" href="index.html">Rudi kwenye app</a>
</div>
<!-- Fomu -->
<div id="form" class="hide">
<h1>Weka nenosiri jipya</h1>
<p class="sub">Andika nenosiri jipya la akaunti yako.</p>
<div class="field">
<label for="p1">Nenosiri jipya</label>
<input id="p1" type="password" autocomplete="new-password" placeholder="Angalau herufi 8">
<button class="eye" type="button" data-for="p1" aria-label="Onyesha nenosiri">👁</button>
</div>
<div class="track"><div class="fill" id="fill"></div></div>
<div class="strength" id="strength"></div>
<div class="field">
<label for="p2">Rudia nenosiri</label>
<input id="p2" type="password" autocomplete="new-password" placeholder="Rudia nenosiri">
<button class="eye" type="button" data-for="p2" aria-label="Onyesha nenosiri">👁</button>
</div>
<button class="btn" id="save">Badilisha nenosiri</button>
<div class="msg" id="msg"></div>
</div>
<!-- Imefanikiwa -->
<div id="done" class="hide">
<div class="big">✅</div>
<h1>Nenosiri limebadilishwa</h1>
<p class="sub">Sasa unaweza kuingia kwa nenosiri lako jipya.</p>
<a class="btn" href="index.html">Ingia kwenye JAYNES MAX</a>
</div>
</div>
<script src="config.js"></script>
<script>
(function(){
const $ = id => document.getElementById(id);
const AUTH = JM_CONFIG.PROFILE_URL + '/auth/v1';
const KEY = JM_CONFIG.PROFILE_KEY;
const show = id => { ['bad','form','done'].forEach(x => $(x).classList.toggle('hide', x !== id)); };
// Supabase huweka token kwenye hash ya kiungo: #access_token=...&type=recovery
const params = new URLSearchParams(location.hash.replace(/^#/, ''));
const token = params.get('access_token');
const type = params.get('type');
const errCode = params.get('error_code');
try { history.replaceState(null, '', location.pathname); } catch (_) {} // ficha token kwenye URL
if (errCode === 'otp_expired') {
$('badText').textContent = 'Kiungo kimeisha muda au kimeshatumika. Omba kingine kupitia "Umesahau nenosiri?" kwenye app.';
show('bad');
} else if (!token || type !== 'recovery') {
show('bad');
} else {
show('form');
}
document.querySelectorAll('.eye').forEach(b => b.onclick = () => {
const i = $(b.dataset.for); i.type = i.type === 'password' ? 'text' : 'password';
});
$('p1').addEventListener('input', () => {
const v = $('p1').value;
let s = 0;
if (v.length >= 8) s++;
if (v.length >= 12) s++;
if (/[a-z]/.test(v) && /[A-Z]/.test(v)) s++;
if (/\d/.test(v)) s++;
if (/[^A-Za-z0-9]/.test(v)) s++;
if (!v) s = 0;
const lv = [
['0%', '#ff5252', ''], ['25%', '#ff5252', 'Dhaifu'], ['45%', '#ffb74d', 'Wastani'],
['70%', '#ffd54f', 'Nzuri'], ['90%', '#9ccc65', 'Imara'], ['100%', '#5ee6a0', 'Imara sana']
][s];
$('fill').style.width = lv[0]; $('fill').style.background = lv[1]; $('strength').textContent = lv[2];
});
const msg = (t, cls) => { $('msg').textContent = t; $('msg').className = 'msg ' + (cls || ''); };
$('save').onclick = async () => {
const a = $('p1').value, b = $('p2').value;
if (a.length < 8) return msg('Nenosiri liwe angalau herufi 8.', 'err');
if (a !== b) return msg('Manenosiri hayalingani.', 'err');
$('save').disabled = true; msg('Subiri…');
try {
const res = await fetch(AUTH + '/user', {
method: 'PUT',
headers: { 'Content-Type': 'application/json', 'apikey': KEY, 'Authorization': 'Bearer ' + token },
body: JSON.stringify({ password: a })
});
const d = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(d.msg || d.error_description || d.error_code || 'Imeshindikana');
show('done');
} catch (e) {
const m = String(e.message || '');
msg(/same|different/i.test(m) ? 'Nenosiri jipya lazima lisiwe sawa na la zamani.'
: /expired|invalid|jwt/i.test(m) ? 'Kiungo kimeisha muda. Omba kingine kwenye app.'
: 'Imeshindikana: ' + m, 'err');
$('save').disabled = false;
}
};
[$('p1'), $('p2')].forEach(i => i.addEventListener('keydown', e => { if (e.key === 'Enter') $('save').click(); }));
})();
</script>
</body>
</html>
|