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:
ske087
2025-08-09 20:44:25 +03:00
parent d1e2b95678
commit 1661f5f588
14 changed files with 2742 additions and 34 deletions

View File

@@ -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) {