Jul 2nd - Optimized code
This commit is contained in:
@@ -6,8 +6,13 @@
|
||||
<style>:root { --accent: {{ branding.primary_color }}; --accent-h: {{ branding.primary_color }}; }</style>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600&display=swap" rel="stylesheet"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet"/>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/password-strength.css') }}"/>
|
||||
<style>
|
||||
:root{--bg:#f0f4f8;--border:#e2e8f0;--accent:#2563eb;--accent-h:#1d4ed8;--text:#0f172a;--text2:#334155;--muted:#64748b;--danger:#dc2626;--danger-bg:#fef2f2;}
|
||||
:root{
|
||||
--bg:#f0f4f8;--border:#e2e8f0;--border2:#cbd5e1;
|
||||
--accent:#2563eb;--accent-h:#1d4ed8;--text:#0f172a;--text2:#334155;--muted:#64748b;
|
||||
--success:#059669;--danger:#dc2626;--danger-bg:#fef2f2;
|
||||
}
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:'DM Sans',sans-serif;background:var(--bg);min-height:100vh;display:flex;align-items:center;justify-content:center;}
|
||||
.bg-grid{position:fixed;inset:0;background-image:linear-gradient(var(--border) 1px,transparent 1px),linear-gradient(90deg,var(--border) 1px,transparent 1px);background-size:48px 48px;opacity:.6;pointer-events:none;}
|
||||
@@ -23,13 +28,11 @@
|
||||
input::placeholder{color:#94a3b8;}
|
||||
.btn{width:100%;background:var(--accent);border:none;color:#fff;border-radius:9px;padding:12px;font-size:14px;font-weight:600;cursor:pointer;transition:background .15s;font-family:inherit;box-shadow:0 2px 6px rgba(37,99,235,.3);}
|
||||
.btn:hover{background:var(--accent-h);}
|
||||
.btn:disabled{background:#93c5fd;cursor:not-allowed;box-shadow:none;}
|
||||
.links{text-align:center;margin-top:18px;font-size:13px;color:var(--muted);}
|
||||
.links a{color:var(--accent);}
|
||||
.alert{border-radius:8px;padding:11px 14px;font-size:13px;margin-bottom:18px;}
|
||||
.alert-danger{background:var(--danger-bg);color:var(--danger);border:1px solid #fecaca;}
|
||||
/* strength meter */
|
||||
#pw-strength-bar{height:4px;border-radius:2px;transition:width .3s,background .3s;background:#e2e8f0;width:0;}
|
||||
#pw-strength-text{font-size:11px;color:var(--muted);margin-top:4px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -53,46 +56,90 @@
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
|
||||
<form method="POST">
|
||||
<form method="POST" id="reset-form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div class="form-group">
|
||||
<label>New Password</label>
|
||||
<input type="password" name="password" id="pw-new" required placeholder="Min. 8 characters" autofocus
|
||||
oninput="checkStrength(this.value)"/>
|
||||
<div style="margin-top:6px;background:#e2e8f0;border-radius:2px;height:4px;">
|
||||
<div id="pw-strength-bar"></div>
|
||||
<div class="pw-wrap">
|
||||
<input type="password" name="password" id="pw-new" required maxlength="128"
|
||||
placeholder="Min. 8 characters" autofocus
|
||||
autocomplete="new-password"/>
|
||||
<button type="button" class="pw-toggle" id="pw-new-toggle"
|
||||
title="Show / hide password" tabindex="-1">
|
||||
<i class="bi bi-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Strength bar -->
|
||||
<div class="pw-strength-wrap" id="strength-wrap" style="display:none;">
|
||||
<div class="pw-strength-track">
|
||||
<div class="pw-strength-fill" id="strength-bar"></div>
|
||||
</div>
|
||||
<div class="pw-strength-label" id="strength-label"></div>
|
||||
</div>
|
||||
|
||||
<!-- Rule checklist — mirrors server-side validate_password() rules -->
|
||||
<div class="pw-rules" id="rules-box" style="display:none;">
|
||||
<div class="pw-rule unmet" id="rule-len">
|
||||
<span class="ri"><i class="bi bi-circle"></i></span>
|
||||
<span>8+ characters</span>
|
||||
</div>
|
||||
<div class="pw-rule unmet" id="rule-upper">
|
||||
<span class="ri"><i class="bi bi-circle"></i></span>
|
||||
<span>Uppercase letter</span>
|
||||
</div>
|
||||
<div class="pw-rule unmet" id="rule-digit">
|
||||
<span class="ri"><i class="bi bi-circle"></i></span>
|
||||
<span>Number</span>
|
||||
</div>
|
||||
<div class="pw-rule unmet" id="rule-special">
|
||||
<span class="ri"><i class="bi bi-circle"></i></span>
|
||||
<span>Special character</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="pw-strength-text"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Confirm Password</label>
|
||||
<input type="password" name="confirm_password" required placeholder="Repeat password"/>
|
||||
<div class="pw-wrap">
|
||||
<input type="password" name="confirm_password" id="pw-confirm" required maxlength="128"
|
||||
placeholder="Repeat password"
|
||||
autocomplete="new-password"/>
|
||||
<button type="button" class="pw-toggle" id="pw-confirm-toggle"
|
||||
title="Show / hide password" tabindex="-1">
|
||||
<i class="bi bi-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="pw-match" id="match-msg"></div>
|
||||
</div>
|
||||
<button type="submit" class="btn"><i class="bi bi-lock me-2"></i>Update Password</button>
|
||||
<button type="submit" class="btn" id="submit-btn"><i class="bi bi-lock me-2"></i>Update Password</button>
|
||||
</form>
|
||||
<div class="links"><a href="{{ url_for('auth.login') }}">← Back to Sign In</a></div>
|
||||
</div>
|
||||
<script src="{{ url_for('static', filename='js/password-strength.js') }}"></script>
|
||||
<script>
|
||||
function checkStrength(pw) {
|
||||
let score = 0;
|
||||
if (pw.length >= 8) score++;
|
||||
if (/[A-Z]/.test(pw)) score++;
|
||||
if (/[0-9]/.test(pw)) score++;
|
||||
if (/[^A-Za-z0-9]/.test(pw)) score++;
|
||||
const bar = document.getElementById('pw-strength-bar');
|
||||
const text = document.getElementById('pw-strength-text');
|
||||
const levels = [
|
||||
{ w: '0%', bg: '#e2e8f0', label: '' },
|
||||
{ w: '25%', bg: '#dc2626', label: 'Weak' },
|
||||
{ w: '50%', bg: '#d97706', label: 'Fair' },
|
||||
{ w: '75%', bg: '#2563eb', label: 'Good' },
|
||||
{ w: '100%', bg: '#059669', label: 'Strong' },
|
||||
];
|
||||
const lvl = levels[score] || levels[0];
|
||||
bar.style.width = lvl.w;
|
||||
bar.style.background = lvl.bg;
|
||||
text.textContent = lvl.label;
|
||||
text.style.color = lvl.bg;
|
||||
const pwStrength = PasswordStrength.init({
|
||||
password : 'pw-new',
|
||||
confirm : 'pw-confirm',
|
||||
strengthBar : 'strength-bar',
|
||||
strengthLabel: 'strength-label',
|
||||
strengthWrap : 'strength-wrap',
|
||||
rulesWrap : 'rules-box',
|
||||
rules: { len: 'rule-len', upper: 'rule-upper', digit: 'rule-digit', special: 'rule-special' },
|
||||
matchMsg : 'match-msg',
|
||||
toggles: [
|
||||
{ input: 'pw-new', button: 'pw-new-toggle' },
|
||||
{ input: 'pw-confirm', button: 'pw-confirm-toggle' },
|
||||
],
|
||||
onChange: updateSubmitState,
|
||||
});
|
||||
|
||||
function updateSubmitState() {
|
||||
const pw = document.getElementById('pw-new').value;
|
||||
const pw2 = document.getElementById('pw-confirm').value;
|
||||
const btn = document.getElementById('submit-btn');
|
||||
const match = pw === pw2 && pw2.length > 0;
|
||||
const hasStarted = pw.length > 0 || pw2.length > 0;
|
||||
btn.disabled = hasStarted && !(PasswordStrength.allRulesMet(pw) && match);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user