04/06 adding some additional functions

This commit is contained in:
2026-04-06 18:02:16 -04:00
parent bc236a3d19
commit 299bf2ca05
12 changed files with 1142 additions and 9 deletions
+122 -2
View File
@@ -73,11 +73,51 @@
<div class="row g-3 mb-4">
<div class="col-md-6">
<label class="form-label">New Password</label>
<input type="password" class="form-control" name="new_password" placeholder="Min. 8 characters"/>
<!-- Show/hide toggle wrapper -->
<div style="position:relative;">
<input type="password" class="form-control" name="new_password"
id="prof-pw" placeholder="Min. 8 characters"
autocomplete="new-password"
oninput="profPwInput()" style="padding-right:40px;"/>
<button type="button" id="prof-pw-toggle"
onclick="profToggle('prof-pw','prof-pw-toggle')"
tabindex="-1"
style="position:absolute;right:10px;top:50%;transform:translateY(-50%);
background:none;border:none;color:var(--muted);cursor:pointer;font-size:15px;">
<i class="bi bi-eye"></i>
</button>
</div>
<!-- Strength bar (hidden until typing starts) -->
<div id="prof-strength-wrap" style="display:none;margin-top:6px;">
<div style="height:4px;background:var(--border);border-radius:2px;overflow:hidden;margin-bottom:5px;">
<div id="prof-strength-bar" style="height:100%;border-radius:2px;width:0%;transition:width .3s,background .3s;"></div>
</div>
<div id="prof-strength-label" style="font-size:11px;font-weight:600;font-family:'Space Mono',monospace;display:flex;align-items:center;gap:5px;"></div>
</div>
<!-- Rule checklist -->
<div id="prof-rules" style="display:none;margin-top:7px;background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:9px 12px;display:grid;grid-template-columns:1fr 1fr;gap:3px 10px;">
<div class="prof-rule" id="prof-rule-len" style="display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);"><span class="prof-ri"><i class="bi bi-circle"></i></span> 8+ characters</div>
<div class="prof-rule" id="prof-rule-upper" style="display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);"><span class="prof-ri"><i class="bi bi-circle"></i></span> Uppercase letter</div>
<div class="prof-rule" id="prof-rule-digit" style="display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);"><span class="prof-ri"><i class="bi bi-circle"></i></span> Number</div>
<div class="prof-rule" id="prof-rule-special"style="display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);"><span class="prof-ri"><i class="bi bi-circle"></i></span> Special character</div>
</div>
</div>
<div class="col-md-6">
<label class="form-label">Confirm Password</label>
<input type="password" class="form-control" name="confirm_password" placeholder="Repeat password"/>
<div style="position:relative;">
<input type="password" class="form-control" name="confirm_password"
id="prof-pw2" placeholder="Repeat password"
autocomplete="new-password"
oninput="profConfirmInput()" style="padding-right:40px;"/>
<button type="button" id="prof-pw2-toggle"
onclick="profToggle('prof-pw2','prof-pw2-toggle')"
tabindex="-1"
style="position:absolute;right:10px;top:50%;transform:translateY(-50%);
background:none;border:none;color:var(--muted);cursor:pointer;font-size:15px;">
<i class="bi bi-eye"></i>
</button>
</div>
<div id="prof-match-msg" style="font-size:11.5px;margin-top:6px;font-family:'Space Mono',monospace;font-weight:600;min-height:18px;"></div>
</div>
</div>
@@ -90,4 +130,84 @@
</div>
</div>
</div>
{% block scripts %}
<script>
// ── Profile page password strength — mirrors register.html rules exactly ──────
const PROF_RULES = {
len: pw => pw.length >= 8,
upper: pw => /[A-Z]/.test(pw),
digit: pw => /\d/.test(pw),
special: pw => /[!@#$%^&*()\-_=+\[\]{};:'",.<>?/\|`~]/.test(pw),
};
const PROF_LEVELS = [
{ label:'Very Weak', color:'#ef4444', pct:12 },
{ label:'Weak', color:'#f97316', pct:30 },
{ label:'Fair', color:'#eab308', pct:52 },
{ label:'Good', color:'#22c55e', pct:76 },
{ label:'Strong', color:'#059669', pct:100 },
];
function profScore(pw) {
return [PROF_RULES.len,PROF_RULES.upper,PROF_RULES.digit,PROF_RULES.special]
.filter(r => r(pw)).length + (pw.length >= 16 ? 1 : 0);
}
function profSetRule(id, met) {
const el = document.getElementById('prof-rule-' + id);
if (!el) return;
el.style.color = met ? 'var(--success)' : 'var(--muted)';
el.querySelector('.prof-ri').innerHTML = met
? '<i class="bi bi-check-circle-fill" style="color:var(--success);"></i>'
: '<i class="bi bi-circle"></i>';
}
function profPwInput() {
const pw = document.getElementById('prof-pw').value;
const wrap = document.getElementById('prof-strength-wrap');
const rules = document.getElementById('prof-rules');
const bar = document.getElementById('prof-strength-bar');
const lbl = document.getElementById('prof-strength-label');
if (!pw) {
wrap.style.display = 'none'; rules.style.display = 'none';
document.getElementById('prof-pw').classList.remove('is-valid','is-invalid');
profConfirmInput(); return;
}
wrap.style.display = 'block'; rules.style.display = 'grid';
profSetRule('len', PROF_RULES.len(pw));
profSetRule('upper', PROF_RULES.upper(pw));
profSetRule('digit', PROF_RULES.digit(pw));
profSetRule('special', PROF_RULES.special(pw));
const score = profScore(pw);
const lvl = PROF_LEVELS[Math.max(0, score - 1)] || PROF_LEVELS[0];
bar.style.width = lvl.pct + '%';
bar.style.background = lvl.color;
lbl.style.color = lvl.color;
const icon = score >= 4 ? 'shield-fill' : score >= 2 ? 'shield-half' : 'shield';
lbl.innerHTML = `<i class="bi bi-${icon}"></i> ${lvl.label}`;
const allMet = Object.values(PROF_RULES).every(r => r(pw));
document.getElementById('prof-pw').classList.toggle('is-valid', allMet);
document.getElementById('prof-pw').classList.toggle('is-invalid', !allMet);
profConfirmInput();
}
function profConfirmInput() {
const pw = document.getElementById('prof-pw').value;
const pw2 = document.getElementById('prof-pw2').value;
const msg = document.getElementById('prof-match-msg');
const el2 = document.getElementById('prof-pw2');
if (!pw2) { msg.innerHTML=''; el2.classList.remove('is-valid','is-invalid'); return; }
const ok = pw === pw2;
msg.innerHTML = ok
? '<span style="color:var(--success);"><i class="bi bi-check-circle-fill me-1"></i>Passwords match</span>'
: '<span style="color:var(--danger);"><i class="bi bi-x-circle-fill me-1"></i>Passwords do not match</span>';
el2.classList.toggle('is-valid', ok);
el2.classList.toggle('is-invalid', !ok);
}
function profToggle(inputId, btnId) {
const inp = document.getElementById(inputId);
const btn = document.getElementById(btnId);
const isPassword = inp.type === 'password';
inp.type = isPassword ? 'text' : 'password';
btn.querySelector('i').className = isPassword ? 'bi bi-eye-slash' : 'bi bi-eye';
}
</script>
{% endblock %}
{% endblock %}