Features Added: 🔥 Modern Chat System: - Real-time messaging with modern Tailwind CSS design - Post-linked discussions for adventure sharing - Chat categories (general, technical-support, adventure-planning) - Mobile-responsive interface with gradient backgrounds - JavaScript polling for live message updates 🎯 Comprehensive Admin Panel: - Chat room management with merge capabilities - Password reset system with email templates - User management with admin controls - Chat statistics and analytics dashboard - Room binding to posts and categorization �� Mobile API Integration: - RESTful API endpoints at /api/v1/chat - Session-based authentication for mobile apps - Comprehensive endpoints for rooms, messages, users - Mobile app compatibility (React Native, Flutter) 🛠️ Technical Improvements: - Enhanced database models with ChatRoom categories - Password reset token system with email verification - Template synchronization fixes for Docker deployment - Migration scripts for database schema updates - Improved error handling and validation 🎨 UI/UX Enhancements: - Modern card-based layouts matching app design - Consistent styling across chat and admin interfaces - Mobile-optimized touch interactions - Professional gradient designs and glass morphism effects 📚 Documentation: - Updated README with comprehensive API documentation - Added deployment instructions for Docker (port 8100) - Configuration guide for production environments - Mobile integration examples and endpoints This update transforms the platform into a comprehensive motorcycle adventure community with modern chat capabilities and professional admin management tools.
254 lines
13 KiB
HTML
254 lines
13 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Chat - Community Discussions{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="min-h-screen bg-gradient-to-br from-blue-900 via-purple-900 to-teal-900 pt-16">
|
|
<!-- Header Section -->
|
|
<div class="relative overflow-hidden py-16">
|
|
<div class="absolute inset-0 bg-black/20"></div>
|
|
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
|
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-8 border border-white/20">
|
|
<h1 class="text-4xl font-bold text-white mb-4">
|
|
<i class="fas fa-comments mr-3"></i>Community Chat
|
|
</h1>
|
|
<p class="text-blue-200 text-lg">Connect with fellow motorcycle adventurers</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-12 -mt-8">
|
|
<!-- Community Guidelines Card -->
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden mb-8">
|
|
<div class="bg-gradient-to-r from-green-600 to-emerald-600 p-6">
|
|
<div class="flex items-center text-white">
|
|
<i class="fas fa-shield-alt text-3xl mr-4"></i>
|
|
<div>
|
|
<h3 class="text-xl font-bold">Community Guidelines</h3>
|
|
<p class="text-green-100">Keep our community safe and welcoming</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6 bg-green-50">
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
|
<div class="flex items-start">
|
|
<i class="fas fa-check-circle text-green-500 mr-2 mt-1"></i>
|
|
<span>Be respectful to all community members</span>
|
|
</div>
|
|
<div class="flex items-start">
|
|
<i class="fas fa-check-circle text-green-500 mr-2 mt-1"></i>
|
|
<span>Share motorcycle adventures and tips</span>
|
|
</div>
|
|
<div class="flex items-start">
|
|
<i class="fas fa-check-circle text-green-500 mr-2 mt-1"></i>
|
|
<span>Help others with technical questions</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8 max-w-4xl mx-auto">
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300 hover:shadow-2xl hover:scale-105">
|
|
<div class="bg-gradient-to-r from-green-600 to-emerald-600 p-6">
|
|
<div class="flex items-center text-white">
|
|
<i class="fas fa-plus-circle text-3xl mr-4"></i>
|
|
<div>
|
|
<h4 class="text-xl font-bold">Create Chat Room</h4>
|
|
<p class="text-green-100">Start a new discussion</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6 text-center">
|
|
<p class="text-gray-600 mb-6">Start a new chat room on any motorcycle topic or connect it to a specific post</p>
|
|
<a href="{{ url_for('chat.create_room_form') }}"
|
|
class="inline-flex items-center px-6 py-3 bg-gradient-to-r from-green-600 to-emerald-600 text-white font-semibold rounded-lg hover:from-green-700 hover:to-emerald-700 transition-all duration-200">
|
|
<i class="fas fa-plus mr-2"></i>Create New Room
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300 hover:shadow-2xl hover:scale-105">
|
|
<div class="bg-gradient-to-r from-blue-600 to-purple-600 p-6">
|
|
<div class="flex items-center text-white">
|
|
<i class="fas fa-newspaper text-3xl mr-4"></i>
|
|
<div>
|
|
<h4 class="text-xl font-bold">Post Discussions</h4>
|
|
<p class="text-blue-100">Chat about community posts</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6 text-center">
|
|
<p class="text-gray-600 mb-6">Join discussions about specific community posts and share your thoughts</p>
|
|
<a href="{{ url_for('chat.post_discussions') }}"
|
|
class="inline-flex items-center px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-200">
|
|
<i class="fas fa-comments mr-2"></i>View Discussions
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if user_rooms %}
|
|
<!-- Your Recent Chats -->
|
|
<div class="mb-8">
|
|
<h2 class="text-2xl font-bold text-white mb-6 flex items-center">
|
|
<i class="fas fa-history mr-3"></i>Your Recent Chats
|
|
</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{% for room in user_rooms %}
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300 hover:shadow-2xl hover:scale-105">
|
|
<div class="bg-gradient-to-r
|
|
{% if room.room_type == 'support' %}from-purple-600 to-indigo-600
|
|
{% elif room.room_type == 'public' %}from-blue-600 to-cyan-600
|
|
{% elif room.room_type == 'group' %}from-green-600 to-teal-600
|
|
{% else %}from-gray-600 to-slate-600{% endif %} p-6">
|
|
<div class="flex items-center justify-between text-white">
|
|
<div>
|
|
<h3 class="text-lg font-bold">{{ room.name }}</h3>
|
|
<p class="text-sm opacity-80">{{ room.room_type.replace('_', ' ').title() }}</p>
|
|
</div>
|
|
<i class="fas
|
|
{% if room.room_type == 'support' %}fa-headset
|
|
{% elif room.room_type == 'public' %}fa-users
|
|
{% elif room.room_type == 'group' %}fa-user-friends
|
|
{% else %}fa-comments{% endif %} text-2xl"></i>
|
|
</div>
|
|
</div>
|
|
<div class="p-6">
|
|
<p class="text-gray-600 mb-4">{{ room.description or 'No description available' }}</p>
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-sm text-gray-500">
|
|
<i class="fas fa-clock mr-1"></i>
|
|
{{ room.last_activity.strftime('%m/%d %H:%M') if room.last_activity else 'No activity' }}
|
|
</span>
|
|
<a href="{{ url_for('chat.room', room_id=room.id) }}"
|
|
class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-200">
|
|
<i class="fas fa-sign-in-alt mr-2"></i>Join Chat
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if public_rooms %}
|
|
<!-- Public Chat Rooms -->
|
|
<div class="mb-8">
|
|
<h2 class="text-2xl font-bold text-white mb-6 flex items-center">
|
|
<i class="fas fa-globe mr-3"></i>Public Chat Rooms
|
|
</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{% for room in public_rooms %}
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300 hover:shadow-2xl hover:scale-105">
|
|
<div class="bg-gradient-to-r
|
|
{% if room.room_type == 'support' %}from-purple-600 to-indigo-600
|
|
{% elif room.room_type == 'public' %}from-blue-600 to-cyan-600
|
|
{% elif room.room_type == 'group' %}from-green-600 to-teal-600
|
|
{% else %}from-gray-600 to-slate-600{% endif %} p-6">
|
|
<div class="flex items-center justify-between text-white">
|
|
<div>
|
|
<h3 class="text-lg font-bold">{{ room.name }}</h3>
|
|
<p class="text-sm opacity-80">{{ room.room_type.replace('_', ' ').title() }}</p>
|
|
</div>
|
|
<div class="text-right">
|
|
<i class="fas
|
|
{% if room.room_type == 'support' %}fa-headset
|
|
{% elif room.room_type == 'public' %}fa-users
|
|
{% elif room.room_type == 'group' %}fa-user-friends
|
|
{% else %}fa-comments{% endif %} text-2xl"></i>
|
|
<p class="text-xs mt-1">{{ room.participants.count() }} members</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6">
|
|
<p class="text-gray-600 mb-3">{{ room.description or 'Join the conversation!' }}</p>
|
|
{% if room.related_post %}
|
|
<div class="bg-blue-50 border border-blue-200 rounded-lg p-3 mb-4">
|
|
<p class="text-sm text-blue-700">
|
|
<i class="fas fa-link mr-1"></i>Related to: {{ room.related_post.title }}
|
|
</p>
|
|
</div>
|
|
{% endif %}
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-sm text-gray-500">
|
|
<i class="fas fa-clock mr-1"></i>
|
|
{{ room.last_activity.strftime('%m/%d %H:%M') if room.last_activity else 'No activity' }}
|
|
</span>
|
|
<a href="{{ url_for('chat.room', room_id=room.id) }}"
|
|
class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-200">
|
|
<i class="fas fa-sign-in-alt mr-2"></i>Join Chat
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if not user_rooms and not public_rooms %}
|
|
<!-- Empty State -->
|
|
<div class="text-center py-16">
|
|
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-12 border border-white/20">
|
|
<i class="fas fa-comments text-6xl text-white/50 mb-6"></i>
|
|
<h3 class="text-2xl font-bold text-white mb-4">No chat rooms available</h3>
|
|
<p class="text-blue-200 mb-8">Be the first to start a conversation!</p>
|
|
<a href="{{ url_for('chat.create_room_form') }}"
|
|
class="inline-flex items-center px-6 py-3 bg-gradient-to-r from-green-600 to-emerald-600 text-white font-semibold rounded-lg hover:from-green-700 hover:to-emerald-700 transition-all duration-200">
|
|
<i class="fas fa-plus mr-2"></i>Create First Room
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
// Mobile app detection and API guidance
|
|
if (window.ReactNativeWebView || window.flutter_inappwebview) {
|
|
console.log('Mobile app detected - use API endpoints for better performance');
|
|
document.body.classList.add('mobile-app-view');
|
|
}
|
|
|
|
// Auto-refresh room list every 60 seconds (increased from 30s to reduce server load)
|
|
let refreshInterval;
|
|
function startAutoRefresh() {
|
|
refreshInterval = setInterval(() => {
|
|
if (document.visibilityState === 'visible' && !document.hidden) {
|
|
window.location.reload();
|
|
}
|
|
}, 60000);
|
|
}
|
|
|
|
// Pause refresh when page is hidden
|
|
document.addEventListener('visibilitychange', () => {
|
|
if (document.hidden) {
|
|
clearInterval(refreshInterval);
|
|
} else {
|
|
startAutoRefresh();
|
|
}
|
|
});
|
|
|
|
// Start auto-refresh on page load
|
|
startAutoRefresh();
|
|
|
|
// Smooth scrolling for better UX
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
const target = document.querySelector(this.getAttribute('href'));
|
|
if (target) {
|
|
target.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'start'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|