195 lines
8.7 KiB
HTML
195 lines
8.7 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block sidebar %}{% endblock %}
|
|
|
|
{% block title %}{% trans "Account Activation" %}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="min-h-screen bg-gradient-to-br from-light to-blue-50 flex items-center justify-center py-12 px-4">
|
|
<div class="max-w-2xl w-full">
|
|
<div class="bg-white rounded-2xl shadow-xl p-8 md:p-12">
|
|
<!-- Header -->
|
|
<div class="text-center mb-8">
|
|
<div class="inline-flex items-center justify-center w-20 h-20 bg-navy rounded-full mb-6">
|
|
<i data-lucide="user-plus" class="w-10 h-10 text-white"></i>
|
|
</div>
|
|
<h1 class="text-xl md:text-2xl font-bold text-navy mb-1">
|
|
{% trans "Create Your Account" %}
|
|
</h1>
|
|
<p class="text-sm text-slate">
|
|
{% trans "Set up your account to get started" %}
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Progress -->
|
|
<div class="mb-8">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<span class="text-sm font-medium text-gray-500">{% trans "Final Step" %}</span>
|
|
<span class="text-sm font-medium text-green-600">{% trans "All acknowledgements completed" %}</span>
|
|
</div>
|
|
<div class="w-full bg-gray-200 h-2.5 rounded-full overflow-hidden">
|
|
<div class="bg-gradient-to-r from-green-400 to-green-500 h-full rounded-full w-full"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error Display -->
|
|
<div id="errorDisplay" class="hidden bg-red-50 border border-red-200 rounded-2xl p-4 mb-6">
|
|
<div class="flex items-start gap-3">
|
|
<i data-lucide="alert-circle" class="w-5 h-5 text-red-500 mt-0.5 flex-shrink-0"></i>
|
|
<p id="errorText" class="text-sm text-red-700"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form -->
|
|
<form id="activationForm" onsubmit="submitActivation(event)" class="space-y-6">
|
|
{% csrf_token %}
|
|
|
|
<div>
|
|
<label class="block text-sm font-bold text-slate mb-2">
|
|
{% trans "Full Name" %}
|
|
</label>
|
|
<input type="text" value="{{ user.get_full_name }}" readonly
|
|
class="w-full px-4 py-3 bg-slate-50 border-2 border-slate-200 rounded-xl text-slate cursor-not-allowed">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-bold text-slate mb-2">
|
|
{% trans "Email Address" %}
|
|
</label>
|
|
<input type="email" value="{{ user.email }}" readonly
|
|
class="w-full px-4 py-3 bg-slate-50 border-2 border-slate-200 rounded-xl text-slate cursor-not-allowed">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-bold text-slate mb-2">
|
|
{% trans "Username" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="text" id="username" name="username" required minlength="3" maxlength="150"
|
|
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl focus:border-navy focus:ring-2 focus:ring-navy/20 outline-none transition"
|
|
placeholder="{% trans 'Choose a username' %}">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-bold text-slate mb-2">
|
|
{% trans "Password" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="password" id="password" name="password" required minlength="8"
|
|
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl focus:border-navy focus:ring-2 focus:ring-navy/20 outline-none transition"
|
|
placeholder="{% trans 'Create a strong password (min 8 characters)' %}">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-bold text-slate mb-2">
|
|
{% trans "Confirm Password" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="password" id="password_confirm" name="password_confirm" required minlength="8"
|
|
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl focus:border-navy focus:ring-2 focus:ring-navy/20 outline-none transition"
|
|
placeholder="{% trans 'Confirm your password' %}">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-bold text-slate mb-2">
|
|
{% trans "Signature" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="text" id="signature" name="signature" required autocomplete="name"
|
|
class="w-full px-4 py-3 border-2 border-slate-200 rounded-xl focus:border-navy focus:ring-2 focus:ring-navy/20 outline-none transition text-lg"
|
|
placeholder="{% trans 'Type your full name as signature' %}">
|
|
<p class="text-xs text-slate mt-1">{% trans "This will be recorded as your digital signature for account activation." %}</p>
|
|
</div>
|
|
|
|
<button type="submit" id="submitBtn" class="w-full bg-navy text-white px-6 py-4 rounded-xl font-bold hover:bg-blue transition shadow-lg">
|
|
{% trans "Activate Account" %}
|
|
<i data-lucide="arrow-right" class="w-5 h-5 inline ml-2"></i>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
lucide.createIcons();
|
|
});
|
|
|
|
function hideError() {
|
|
document.getElementById('errorDisplay').classList.add('hidden');
|
|
}
|
|
|
|
function showError(message) {
|
|
document.getElementById('errorText').textContent = message;
|
|
document.getElementById('errorDisplay').classList.remove('hidden');
|
|
document.getElementById('errorDisplay').scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
}
|
|
|
|
function submitActivation(event) {
|
|
event.preventDefault();
|
|
hideError();
|
|
|
|
const username = document.getElementById('username').value.trim();
|
|
const password = document.getElementById('password').value;
|
|
const password_confirm = document.getElementById('password_confirm').value;
|
|
const signature = document.getElementById('signature').value.trim();
|
|
const csrfToken = document.querySelector('input[name="csrfmiddlewaretoken"]')?.value;
|
|
|
|
if (!username || !password || !password_confirm || !signature) {
|
|
showError('{% trans "Please fill in all required fields." %}');
|
|
return;
|
|
}
|
|
|
|
const btn = document.getElementById('submitBtn');
|
|
btn.disabled = true;
|
|
btn.innerHTML = '<i data-lucide="loader-2" class="w-5 h-5 inline animate-spin"></i> {% trans "Activating..." %}';
|
|
lucide.createIcons();
|
|
|
|
fetch('/accounts/users/onboarding/complete/', {
|
|
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 => {
|
|
return response.json().then(data => {
|
|
if (!response.ok) {
|
|
if (data.password) {
|
|
throw new Error(data.password.join ? data.password.join(' ') : data.password);
|
|
}
|
|
if (data.username) {
|
|
throw new Error(data.username.join ? data.username.join(' ') : data.username);
|
|
}
|
|
if (data.non_field_errors) {
|
|
throw new Error(data.non_field_errors.join ? data.non_field_errors.join(' ') : data.non_field_errors);
|
|
}
|
|
if (data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
if (data.detail) {
|
|
throw new Error(data.detail);
|
|
}
|
|
throw new Error('{% trans "Activation failed. Please check your input and try again." %}');
|
|
}
|
|
return data;
|
|
});
|
|
})
|
|
.then(data => {
|
|
window.location.href = '/accounts/onboarding/complete/';
|
|
})
|
|
.catch(err => {
|
|
showError(err.message);
|
|
})
|
|
.finally(() => {
|
|
btn.disabled = false;
|
|
btn.innerHTML = '{% trans "Activate Account" %} <i data-lucide="arrow-right" class="w-5 h-5 inline ml-2"></i>';
|
|
lucide.createIcons();
|
|
});
|
|
}
|
|
</script>
|
|
{% endblock %}
|