feat: Complete chat system implementation and password reset enhancement
- Add comprehensive chat system with modern UI design - Implement admin-based password reset system - Fix template syntax errors and 500 server errors - Add chat routes, API endpoints, and database models - Enhance user interface with Tailwind CSS card-based design - Implement community guidelines and quick action features - Add responsive design for mobile and desktop compatibility - Create support chat functionality with admin integration - Fix JavaScript inheritance in base template - Add database migration for chat system tables Features: ✅ Modern chat interface with room management ✅ Admin-based password reset workflow ✅ Real-time chat with mobile app support ✅ Professional UI with gradient cards and hover effects ✅ Community guidelines and safety features ✅ Responsive design for all devices ✅ Error-free template rendering
This commit is contained in:
@@ -68,6 +68,92 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Change Password Card -->
|
||||
<div class="bg-white rounded-2xl shadow-xl overflow-hidden mb-8">
|
||||
<div class="cursor-pointer transition-all duration-200 hover:bg-gray-50" onclick="togglePasswordCard()">
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<i class="fas fa-key text-3xl text-purple-600 mr-4"></i>
|
||||
<div>
|
||||
<h3 class="text-xl font-bold text-gray-900">Change Password</h3>
|
||||
<p class="text-gray-600">Update your account password for security</p>
|
||||
</div>
|
||||
</div>
|
||||
<i id="passwordCardToggle" class="fas fa-chevron-down text-gray-400 text-xl transition-transform duration-200"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Password Change Form (Initially Hidden) -->
|
||||
<div id="passwordChangeForm" class="hidden border-t border-gray-200">
|
||||
<div class="p-6 bg-gray-50">
|
||||
<form id="changePasswordForm" method="POST" action="{{ url_for('auth.change_password') }}" class="space-y-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<!-- Current Password -->
|
||||
<div>
|
||||
<label for="current_password" class="block text-sm font-semibold text-gray-700 mb-2">
|
||||
<i class="fas fa-lock mr-1"></i>Current Password
|
||||
</label>
|
||||
<input type="password"
|
||||
id="current_password"
|
||||
name="current_password"
|
||||
required
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200"
|
||||
placeholder="Enter current password">
|
||||
</div>
|
||||
|
||||
<!-- New Password -->
|
||||
<div>
|
||||
<label for="new_password" class="block text-sm font-semibold text-gray-700 mb-2">
|
||||
<i class="fas fa-key mr-1"></i>New Password
|
||||
</label>
|
||||
<input type="password"
|
||||
id="new_password"
|
||||
name="new_password"
|
||||
required
|
||||
minlength="6"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200"
|
||||
placeholder="Enter new password">
|
||||
</div>
|
||||
|
||||
<!-- Confirm New Password -->
|
||||
<div>
|
||||
<label for="confirm_password" class="block text-sm font-semibold text-gray-700 mb-2">
|
||||
<i class="fas fa-check-circle mr-1"></i>Confirm Password
|
||||
</label>
|
||||
<input type="password"
|
||||
id="confirm_password"
|
||||
name="confirm_password"
|
||||
required
|
||||
minlength="6"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200"
|
||||
placeholder="Confirm new password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Password Requirements -->
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<h4 class="font-semibold text-blue-800 mb-2">Password Requirements:</h4>
|
||||
<ul class="text-sm text-blue-700 space-y-1">
|
||||
<li><i class="fas fa-check text-green-500 mr-1"></i>At least 6 characters long</li>
|
||||
<li><i class="fas fa-info-circle text-blue-500 mr-1"></i>Use a unique password you don't use elsewhere</li>
|
||||
<li><i class="fas fa-shield-alt text-green-500 mr-1"></i>Consider using a mix of letters, numbers, and symbols</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="flex justify-end">
|
||||
<button type="submit"
|
||||
class="inline-flex items-center px-6 py-3 bg-gradient-to-r from-purple-600 to-blue-600 text-white font-semibold rounded-lg hover:from-purple-700 hover:to-blue-700 transition-all duration-200 transform hover:scale-105">
|
||||
<i class="fas fa-save mr-2"></i>Update Password
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Adventures Collection Header -->
|
||||
<div class="bg-white rounded-2xl shadow-xl p-6 mb-8">
|
||||
<div class="flex items-center">
|
||||
@@ -280,6 +366,67 @@ function closeDeleteModal() {
|
||||
document.getElementById('deleteModal').classList.add('hidden');
|
||||
}
|
||||
|
||||
// Password card toggle functionality
|
||||
function togglePasswordCard() {
|
||||
const form = document.getElementById('passwordChangeForm');
|
||||
const toggle = document.getElementById('passwordCardToggle');
|
||||
|
||||
if (form && toggle) {
|
||||
if (form.classList.contains('hidden')) {
|
||||
form.classList.remove('hidden');
|
||||
toggle.classList.remove('fa-chevron-down');
|
||||
toggle.classList.add('fa-chevron-up');
|
||||
} else {
|
||||
form.classList.add('hidden');
|
||||
toggle.classList.remove('fa-chevron-up');
|
||||
toggle.classList.add('fa-chevron-down');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure DOM is loaded before attaching event listeners
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Ensure the toggle function is available globally
|
||||
window.togglePasswordCard = togglePasswordCard;
|
||||
});
|
||||
|
||||
// Password change form validation
|
||||
document.getElementById('changePasswordForm').addEventListener('submit', function(e) {
|
||||
const newPassword = document.getElementById('new_password').value;
|
||||
const confirmPassword = document.getElementById('confirm_password').value;
|
||||
|
||||
if (newPassword !== confirmPassword) {
|
||||
e.preventDefault();
|
||||
alert('New password and confirm password do not match. Please try again.');
|
||||
document.getElementById('confirm_password').focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newPassword.length < 6) {
|
||||
e.preventDefault();
|
||||
alert('Password must be at least 6 characters long.');
|
||||
document.getElementById('new_password').focus();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Real-time password confirmation validation
|
||||
document.getElementById('confirm_password').addEventListener('input', function() {
|
||||
const newPassword = document.getElementById('new_password').value;
|
||||
const confirmPassword = this.value;
|
||||
|
||||
if (confirmPassword && newPassword !== confirmPassword) {
|
||||
this.style.borderColor = '#ef4444';
|
||||
this.style.backgroundColor = '#fef2f2';
|
||||
} else if (confirmPassword && newPassword === confirmPassword) {
|
||||
this.style.borderColor = '#10b981';
|
||||
this.style.backgroundColor = '#f0fdf4';
|
||||
} else {
|
||||
this.style.borderColor = '#d1d5db';
|
||||
this.style.backgroundColor = '#ffffff';
|
||||
}
|
||||
});
|
||||
|
||||
// Close modal when clicking outside
|
||||
document.getElementById('deleteModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
|
||||
Reference in New Issue
Block a user