HH/templates/accounts/onboarding/step_activation.html
Marwan Alwali d7847da450 update
2026-01-12 13:20:34 +03:00

260 lines
11 KiB
HTML

{% extends "layouts/base.html" %}
{% load i18n %}
{% block title %}{% trans "Account Activation" %}{% endblock %}
{% block content %}
<div class="container-fluid py-5">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow-lg border-0">
<div class="card-header bg-success text-white">
<h4 class="mb-0 text-center">
<i class="bi bi-person-check me-2"></i>
{% trans "Create Your Account" %}
</h4>
</div>
<div class="card-body p-5">
<div class="alert alert-success mb-4">
<i class="bi bi-check-circle me-2"></i>
{% trans "Congratulations! You have completed the onboarding process. Now create your account credentials to get started." %}
</div>
<form id="activationForm">
{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">
<i class="bi bi-person me-2"></i>{% trans "Username" %}
</label>
<input type="text"
class="form-control form-control-lg"
id="username"
name="username"
required
minlength="3"
pattern="[a-zA-Z0-9_\-]+"
title="{% trans 'Username can only contain letters, numbers, underscores, and hyphens' %}">
<div class="form-text">
{% trans "Choose a unique username (3+ characters)" %}
</div>
</div>
<div class="mb-3">
<label for="emailDisplay" class="form-label">
<i class="bi bi-envelope me-2"></i>{% trans "Email" %}
</label>
<input type="email"
class="form-control form-control-lg"
id="emailDisplay"
name="emailDisplay"
value="{{ user.email }}"
readonly
style="background-color: #f8f9fa;">
</div>
<div class="mb-3">
<label for="password" class="form-label">
<i class="bi bi-lock me-2"></i>{% trans "Password" %}
</label>
<input type="password"
class="form-control form-control-lg"
id="password"
name="password"
required
minlength="8">
<div class="form-text">
{% trans "Minimum 8 characters" %}
</div>
<!-- Password Strength Indicator -->
<div class="progress mt-2" style="height: 5px;">
<div id="passwordStrength" class="progress-bar"
style="width: 0%"
role="progressbar"></div>
</div>
<small id="passwordStrengthText" class="text-muted"></small>
</div>
<div class="mb-3">
<label for="password_confirm" class="form-label">
<i class="bi bi-lock me-2"></i>{% trans "Confirm Password" %}
</label>
<input type="password"
class="form-control form-control-lg"
id="password_confirm"
name="password_confirm"
required
oninput="checkPasswordMatch()">
<div id="passwordMatch" class="form-text"></div>
</div>
<div class="mb-4">
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i>
{% trans "Your digital signature from the previous step will be attached to your account activation for compliance records." %}
</div>
</div>
<div class="d-grid gap-2">
<button type="submit" id="activateBtn" class="btn btn-success btn-lg">
<i class="bi bi-rocket-takeoff me-2"></i>
{% trans "Activate Account" %}
</button>
<button type="button" onclick="goBack()" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-2"></i>
{% trans "Back" %}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const passwordInput = document.getElementById('password');
const passwordStrength = document.getElementById('passwordStrength');
const passwordStrengthText = document.getElementById('passwordStrengthText');
passwordInput.addEventListener('input', function() {
const password = this.value;
let strength = 0;
let text = '';
let color = '';
if (password.length >= 8) strength += 25;
if (password.match(/[a-z]/)) strength += 25;
if (password.match(/[A-Z]/)) strength += 25;
if (password.match(/[0-9]/)) strength += 25;
if (strength < 25) {
text = '{% trans "Very Weak" %}';
color = 'bg-danger';
} else if (strength < 50) {
text = '{% trans "Weak" %}';
color = 'bg-warning';
} else if (strength < 75) {
text = '{% trans "Good" %}';
color = 'bg-info';
} else {
text = '{% trans "Strong" %}';
color = 'bg-success';
}
passwordStrength.style.width = strength + '%';
passwordStrength.className = 'progress-bar ' + color;
passwordStrengthText.textContent = text;
});
document.getElementById('activationForm').addEventListener('submit', function(e) {
e.preventDefault();
activateAccount();
});
});
function checkPasswordMatch() {
const password = document.getElementById('password').value;
const confirm = document.getElementById('password_confirm').value;
const matchDiv = document.getElementById('passwordMatch');
if (confirm) {
if (password === confirm) {
matchDiv.innerHTML = '<span class="text-success"><i class="bi bi-check"></i> {% trans "Passwords match" %}</span>';
return true;
} else {
matchDiv.innerHTML = '<span class="text-danger"><i class="bi bi-x"></i> {% trans "Passwords do not match" %}</span>';
return false;
}
}
return true;
}
// Helper function to get cookie value
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function activateAccount() {
const form = document.getElementById('activationForm');
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const password_confirm = document.getElementById('password_confirm').value;
const signature = localStorage.getItem('onboardingSignature') || '';
if (!username || !password || !password_confirm) {
alert('{% trans "Please fill in all fields" %}');
return;
}
if (password !== password_confirm) {
alert('{% trans "Passwords do not match" %}');
return;
}
if (password.length < 8) {
alert('{% trans "Password must be at least 8 characters" %}');
return;
}
const activateBtn = document.getElementById('activateBtn');
activateBtn.disabled = true;
activateBtn.innerHTML = '<i class="bi bi-arrow-clockwise fa-spin me-2"></i>{% trans "Activating..." %}';
// Get CSRF token
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]')?.value ||
getCookie('csrftoken');
fetch('/accounts/onboarding/complete-activation/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify({
username: username,
password: password,
password_confirm: password_confirm,
signature: signature
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Clear stored signature
localStorage.removeItem('onboardingSignature');
// Show success message and redirect
window.location.href = '/accounts/onboarding/complete/';
} else {
activateBtn.disabled = false;
activateBtn.innerHTML = '<i class="bi bi-rocket-takeoff me-2"></i>{% trans "Activate Account" %}';
alert('Error: ' + (data.error || 'Failed to activate account'));
}
})
.catch(error => {
console.error('Error:', error);
activateBtn.disabled = false;
activateBtn.innerHTML = '<i class="bi bi-rocket-takeoff me-2"></i>{% trans "Activate Account" %}';
alert('{% trans "An error occurred. Please try again." %}');
});
}
function goBack() {
window.location.href = '/accounts/onboarding/wizard/checklist/';
}
</script>
{% endblock %}