quantumtaskai-caprover/templates/authentication/reset_password.html
thecyberlearn b0e8c917ef Initial clean CapRover deployment - no secrets
Complete Django AI agent marketplace with security optimizations
and clean deployment documentation without any API keys or secrets.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 10:50:55 +05:30

365 lines
10 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Reset Password{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width sections */
.main-container {
max-width: none;
padding: 0;
margin-top: 0;
}
/* Reset password page background */
.reset-password-page {
min-height: calc(100vh - 84px); /* Account for header height */
background: var(--gradient-hero);
display: flex;
align-items: center;
justify-content: center;
padding: clamp(20px, 5vw, 40px);
}
/* Reset password container */
.reset-password-container {
background: rgba(255, 255, 255, 0.95);
border-radius: clamp(16px, 4vw, 24px);
padding: clamp(32px, 8vw, 48px);
box-shadow: 0 20px 60px rgba(30, 64, 175, 0.15);
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(20px);
width: 100%;
max-width: 480px;
position: relative;
overflow: hidden;
}
/* Decorative elements */
.reset-password-container::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 80px;
height: 80px;
background: var(--gradient-primary);
border-top-right-radius: clamp(16px, 4vw, 24px);
border-bottom-left-radius: clamp(16px, 4vw, 24px);
opacity: 0.8;
}
.reset-password-container::after {
content: '🔒';
position: absolute;
top: 24px;
right: 24px;
font-size: 24px;
z-index: 1;
}
/* Header section */
.reset-password-header {
text-align: center;
margin-bottom: clamp(24px, 6vw, 32px);
position: relative;
z-index: 2;
}
.reset-password-title {
font-size: clamp(24px, 6vw, 32px);
font-weight: 700;
color: var(--primary-blue);
margin: 0 0 8px 0;
}
.reset-password-subtitle {
font-size: clamp(14px, 3.5vw, 16px);
color: var(--text-secondary);
margin: 0;
}
/* Form styles */
.reset-password-form {
position: relative;
z-index: 2;
}
.form-group {
margin-bottom: clamp(16px, 4vw, 20px);
}
.form-label {
display: block;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 8px;
font-size: clamp(14px, 3.5vw, 16px);
}
.form-input {
width: 100%;
padding: clamp(14px, 4vw, 18px) clamp(16px, 4vw, 20px);
border: 2px solid var(--border-medium);
border-radius: clamp(8px, 2vw, 12px);
font-size: clamp(14px, 3.5vw, 16px);
transition: all 0.3s ease;
background: white;
min-height: 48px;
box-sizing: border-box;
}
.form-input:focus {
outline: none;
border-color: var(--primary-blue);
box-shadow: 0 0 0 3px rgba(64, 224, 208, 0.1);
}
/* Reset button */
.reset-btn {
width: 100%;
background: var(--gradient-primary);
color: white;
border: none;
padding: clamp(16px, 4vw, 20px);
border-radius: clamp(8px, 2vw, 12px);
font-size: clamp(16px, 4vw, 18px);
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
min-height: 56px;
margin-bottom: clamp(20px, 5vw, 24px);
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.reset-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(30, 64, 175, 0.3);
background: var(--gradient-success);
}
.reset-btn:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(30, 64, 175, 0.2);
}
/* Messages */
.messages {
margin-bottom: clamp(16px, 4vw, 20px);
}
.message {
padding: 12px 16px;
border-radius: clamp(8px, 2vw, 12px);
margin-bottom: 8px;
font-weight: 500;
font-size: clamp(14px, 3.5vw, 16px);
}
.message.success {
background: rgba(16, 185, 129, 0.1);
color: var(--success-dark);
border: 1px solid rgba(16, 185, 129, 0.3);
}
.message.error {
background: rgba(239, 68, 68, 0.1);
color: var(--error-red);
border: 1px solid rgba(239, 68, 68, 0.3);
}
.message.info {
background: rgba(59, 130, 246, 0.1);
color: var(--primary-blue);
border: 1px solid rgba(59, 130, 246, 0.3);
}
/* Auth links */
.reset-password-page .reset-password-container .auth-links {
text-align: center;
padding-top: clamp(16px, 4vw, 20px);
border-top: 1px solid var(--border-light);
}
.reset-password-page .reset-password-container .auth-links p {
margin: 8px 0;
color: var(--text-secondary);
font-size: clamp(14px, 3.5vw, 16px);
}
.reset-password-page .reset-password-container .auth-links a {
color: var(--primary-blue);
text-decoration: none;
font-weight: 600;
transition: color 0.2s ease;
}
.reset-password-page .reset-password-container .auth-links a:hover {
color: var(--primary-blue);
text-decoration: underline;
}
/* Password requirements */
.password-requirements {
background: rgba(64, 224, 208, 0.05);
border-radius: clamp(8px, 2vw, 12px);
padding: clamp(12px, 3vw, 16px);
margin-top: 8px;
border: 1px solid rgba(64, 224, 208, 0.2);
}
.password-requirements h4 {
font-size: clamp(13px, 3vw, 14px);
font-weight: 600;
color: var(--primary-blue);
margin: 0 0 8px 0;
}
.password-requirements ul {
list-style: none;
padding: 0;
margin: 0;
}
.password-requirements li {
display: flex;
align-items: center;
gap: 6px;
margin: 4px 0;
color: var(--text-secondary);
font-size: clamp(12px, 3vw, 13px);
}
.password-requirements li::before {
content: '•';
color: var(--primary-blue);
font-weight: bold;
}
/* Responsive adjustments */
@media (max-width: 480px) {
.reset-password-page {
padding: 16px;
}
.reset-password-container {
padding: 24px;
}
}
</style>
{% endblock %}
{% block content %}
<div class="reset-password-page">
<div class="reset-password-container">
<!-- Header -->
<div class="reset-password-header">
<h1 class="reset-password-title">Reset Password</h1>
<p class="reset-password-subtitle">Enter your new password below</p>
</div>
<!-- Messages -->
{% if messages %}
<div class="messages">
{% for message in messages %}
<div class="message {{ message.tags }}">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
<!-- Reset Password Form -->
<form method="post" class="reset-password-form">
{% csrf_token %}
<div class="form-group">
<label for="password1" class="form-label">New Password</label>
<input
type="password"
id="password1"
name="password1"
class="form-input"
placeholder="Enter your new password"
required
autocomplete="new-password"
minlength="8"
>
<div class="password-requirements">
<h4>Password Requirements:</h4>
<ul>
<li>At least 8 characters long</li>
<li>Mix of letters, numbers, and symbols recommended</li>
<li>Should not be commonly used</li>
</ul>
</div>
</div>
<div class="form-group">
<label for="password2" class="form-label">Confirm New Password</label>
<input
type="password"
id="password2"
name="password2"
class="form-input"
placeholder="Confirm your new password"
required
autocomplete="new-password"
minlength="8"
>
</div>
<button type="submit" class="reset-btn">
🔒 Reset My Password
</button>
</form>
<!-- Auth Links -->
<div class="auth-links">
<p>Remember your password? <a href="{% url 'authentication:login' %}">Sign in</a></p>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
// Focus on password field when page loads
document.addEventListener('DOMContentLoaded', function() {
const passwordField = document.getElementById('password1');
if (passwordField) {
passwordField.focus();
}
// Add loading state to button on form submission
const resetForm = document.querySelector('.reset-password-form');
const resetBtn = document.querySelector('.reset-btn');
if (resetForm && resetBtn) {
resetForm.addEventListener('submit', function() {
resetBtn.innerHTML = '⏳ Resetting password...';
resetBtn.disabled = true;
});
}
// Password confirmation validation
const password1 = document.getElementById('password1');
const password2 = document.getElementById('password2');
function validatePasswords() {
if (password2.value && password1.value !== password2.value) {
password2.setCustomValidity('Passwords do not match');
} else {
password2.setCustomValidity('');
}
}
if (password1 && password2) {
password1.addEventListener('input', validatePasswords);
password2.addEventListener('input', validatePasswords);
}
});
</script>
{% endblock %}