- 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
450 lines
16 KiB
HTML
450 lines
16 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Admin Support - Chat{% endblock %}
|
|
|
|
{% block head %}
|
|
<style>
|
|
.support-container {
|
|
min-height: calc(100vh - 80px);
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
padding: 2rem 0;
|
|
}
|
|
|
|
.support-card {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 20px;
|
|
padding: 2rem;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.support-header {
|
|
text-align: center;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.support-icon {
|
|
width: 80px;
|
|
height: 80px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-size: 2rem;
|
|
margin: 0 auto 1rem;
|
|
}
|
|
|
|
.quick-actions {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
gap: 1rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.action-card {
|
|
background: white;
|
|
border-radius: 15px;
|
|
padding: 1.5rem;
|
|
text-align: center;
|
|
border: 2px solid #e9ecef;
|
|
transition: all 0.3s ease;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
}
|
|
|
|
.action-card:hover {
|
|
border-color: #667eea;
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.15);
|
|
text-decoration: none;
|
|
color: inherit;
|
|
}
|
|
|
|
.action-icon {
|
|
width: 50px;
|
|
height: 50px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-size: 1.2rem;
|
|
margin: 0 auto 1rem;
|
|
}
|
|
|
|
.support-form {
|
|
background: white;
|
|
border-radius: 15px;
|
|
padding: 2rem;
|
|
border: 2px solid #e9ecef;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-control {
|
|
border: 2px solid #e9ecef;
|
|
border-radius: 10px;
|
|
padding: 0.75rem 1rem;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.form-control:focus {
|
|
border-color: #667eea;
|
|
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
|
|
}
|
|
|
|
.priority-selector {
|
|
display: flex;
|
|
gap: 1rem;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.priority-option {
|
|
flex: 1;
|
|
padding: 0.75rem;
|
|
border: 2px solid #e9ecef;
|
|
border-radius: 10px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.priority-option.active {
|
|
border-color: #667eea;
|
|
background: #f8f9ff;
|
|
}
|
|
|
|
.priority-low { border-left: 4px solid #28a745; }
|
|
.priority-medium { border-left: 4px solid #ffc107; }
|
|
.priority-high { border-left: 4px solid #dc3545; }
|
|
|
|
.recent-tickets {
|
|
background: white;
|
|
border-radius: 15px;
|
|
padding: 1.5rem;
|
|
border: 2px solid #e9ecef;
|
|
}
|
|
|
|
.ticket-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 1rem;
|
|
border-bottom: 1px solid #e9ecef;
|
|
transition: background 0.2s ease;
|
|
}
|
|
|
|
.ticket-item:hover {
|
|
background: #f8f9fa;
|
|
}
|
|
|
|
.ticket-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.ticket-status {
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
margin-right: 1rem;
|
|
}
|
|
|
|
.status-open { background: #28a745; }
|
|
.status-pending { background: #ffc107; }
|
|
.status-closed { background: #6c757d; }
|
|
|
|
.ticket-info {
|
|
flex: 1;
|
|
}
|
|
|
|
.ticket-title {
|
|
font-weight: 600;
|
|
color: #495057;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.ticket-meta {
|
|
font-size: 0.875rem;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.btn-gradient {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
border: none;
|
|
border-radius: 10px;
|
|
padding: 0.75rem 2rem;
|
|
color: white;
|
|
font-weight: 600;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.btn-gradient:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3);
|
|
color: white;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.support-container {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.support-card {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.quick-actions {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.priority-selector {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="support-container">
|
|
<div class="container">
|
|
<div class="support-card">
|
|
<div class="support-header">
|
|
<div class="support-icon">
|
|
<i class="fas fa-headset"></i>
|
|
</div>
|
|
<h2>Admin Support</h2>
|
|
<p class="text-muted">Get help from our administrators for account issues, password resets, and technical support</p>
|
|
</div>
|
|
|
|
<div class="quick-actions">
|
|
<a href="#" class="action-card" onclick="startPasswordReset()">
|
|
<div class="action-icon">
|
|
<i class="fas fa-key"></i>
|
|
</div>
|
|
<h5>Password Reset</h5>
|
|
<p class="text-muted">Reset your account password with admin assistance</p>
|
|
</a>
|
|
|
|
<a href="#" class="action-card" onclick="startAccountIssue()">
|
|
<div class="action-icon">
|
|
<i class="fas fa-user-cog"></i>
|
|
</div>
|
|
<h5>Account Issues</h5>
|
|
<p class="text-muted">Login problems, profile updates, and account settings</p>
|
|
</a>
|
|
|
|
<a href="#" class="action-card" onclick="startTechnicalSupport()">
|
|
<div class="action-icon">
|
|
<i class="fas fa-tools"></i>
|
|
</div>
|
|
<h5>Technical Support</h5>
|
|
<p class="text-muted">App bugs, feature requests, and technical assistance</p>
|
|
</a>
|
|
|
|
<a href="#" class="action-card" onclick="startGeneralInquiry()">
|
|
<div class="action-icon">
|
|
<i class="fas fa-question-circle"></i>
|
|
</div>
|
|
<h5>General Inquiry</h5>
|
|
<p class="text-muted">Questions about features, policies, or general help</p>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-lg-8">
|
|
<div class="support-form">
|
|
<h4 class="mb-3">Create Support Ticket</h4>
|
|
<form id="supportForm">
|
|
<div class="form-group">
|
|
<label for="subject" class="form-label">Subject</label>
|
|
<input type="text" class="form-control" id="subject" name="subject" required
|
|
placeholder="Brief description of your issue">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="category" class="form-label">Category</label>
|
|
<select class="form-control" id="category" name="category" required>
|
|
<option value="">Select a category</option>
|
|
<option value="password_reset">Password Reset</option>
|
|
<option value="account_issues">Account Issues</option>
|
|
<option value="technical_support">Technical Support</option>
|
|
<option value="general_inquiry">General Inquiry</option>
|
|
<option value="bug_report">Bug Report</option>
|
|
<option value="feature_request">Feature Request</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Priority</label>
|
|
<div class="priority-selector">
|
|
<div class="priority-option priority-low" data-priority="low">
|
|
<strong>Low</strong><br>
|
|
<small>General questions</small>
|
|
</div>
|
|
<div class="priority-option priority-medium active" data-priority="medium">
|
|
<strong>Medium</strong><br>
|
|
<small>Account issues</small>
|
|
</div>
|
|
<div class="priority-option priority-high" data-priority="high">
|
|
<strong>High</strong><br>
|
|
<small>Urgent problems</small>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" id="priority" name="priority" value="medium">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="description" class="form-label">Description</label>
|
|
<textarea class="form-control" id="description" name="description" rows="6" required
|
|
placeholder="Please provide detailed information about your issue..."></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="contactMethod" class="form-label">Preferred Contact Method</label>
|
|
<select class="form-control" id="contactMethod" name="contact_method">
|
|
<option value="chat">Chat (Recommended)</option>
|
|
<option value="email">Email Notification</option>
|
|
</select>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-gradient btn-lg">
|
|
<i class="fas fa-paper-plane me-2"></i>
|
|
Submit Support Request
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-4">
|
|
<div class="recent-tickets">
|
|
<h5 class="mb-3">Your Recent Tickets</h5>
|
|
{% if recent_tickets %}
|
|
{% for ticket in recent_tickets %}
|
|
<div class="ticket-item">
|
|
<div class="ticket-status status-{{ ticket.status }}"></div>
|
|
<div class="ticket-info">
|
|
<div class="ticket-title">{{ ticket.subject }}</div>
|
|
<div class="ticket-meta">
|
|
{{ ticket.created_at.strftime('%b %d, %Y') }} •
|
|
{{ ticket.category.replace('_', ' ').title() }}
|
|
</div>
|
|
</div>
|
|
<a href="{{ url_for('chat.room', room_id=ticket.chat_room_id) }}" class="btn btn-sm btn-outline-primary">
|
|
View
|
|
</a>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<p class="text-muted text-center">No recent support tickets</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="recent-tickets mt-3">
|
|
<h6 class="mb-3">Support Information</h6>
|
|
<div class="alert alert-info">
|
|
<i class="fas fa-info-circle"></i>
|
|
<strong>Response Time:</strong> Most tickets are answered within 2-4 hours during business hours.
|
|
</div>
|
|
<div class="alert alert-warning">
|
|
<i class="fas fa-clock"></i>
|
|
<strong>Business Hours:</strong> Monday-Friday, 9 AM - 6 PM (Local Time)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Priority selector handling
|
|
document.querySelectorAll('.priority-option').forEach(option => {
|
|
option.addEventListener('click', function() {
|
|
document.querySelectorAll('.priority-option').forEach(opt => opt.classList.remove('active'));
|
|
this.classList.add('active');
|
|
document.getElementById('priority').value = this.dataset.priority;
|
|
});
|
|
});
|
|
|
|
// Quick action handlers
|
|
function startPasswordReset() {
|
|
document.getElementById('subject').value = 'Password Reset Request';
|
|
document.getElementById('category').value = 'password_reset';
|
|
document.getElementById('description').value = 'I need help resetting my password. ';
|
|
document.getElementById('description').focus();
|
|
}
|
|
|
|
function startAccountIssue() {
|
|
document.getElementById('subject').value = 'Account Issue';
|
|
document.getElementById('category').value = 'account_issues';
|
|
document.getElementById('description').value = 'I am experiencing issues with my account: ';
|
|
document.getElementById('description').focus();
|
|
}
|
|
|
|
function startTechnicalSupport() {
|
|
document.getElementById('subject').value = 'Technical Support Request';
|
|
document.getElementById('category').value = 'technical_support';
|
|
document.getElementById('description').value = 'I need technical assistance with: ';
|
|
document.getElementById('description').focus();
|
|
}
|
|
|
|
function startGeneralInquiry() {
|
|
document.getElementById('subject').value = 'General Inquiry';
|
|
document.getElementById('category').value = 'general_inquiry';
|
|
document.getElementById('description').value = 'I have a question about: ';
|
|
document.getElementById('description').focus();
|
|
}
|
|
|
|
// Support form submission
|
|
document.getElementById('supportForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(this);
|
|
const submitButton = this.querySelector('button[type="submit"]');
|
|
const originalText = submitButton.innerHTML;
|
|
|
|
// Disable button and show loading
|
|
submitButton.disabled = true;
|
|
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Creating Ticket...';
|
|
|
|
fetch('/api/v1/chat/support/create', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('Support ticket created successfully! You will be redirected to the chat room.');
|
|
window.location.href = `/chat/room/${data.room_id}`;
|
|
} else {
|
|
alert('Error creating support ticket: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Failed to create support ticket. Please try again.');
|
|
})
|
|
.finally(() => {
|
|
submitButton.disabled = false;
|
|
submitButton.innerHTML = originalText;
|
|
});
|
|
});
|
|
|
|
// Mobile app integration
|
|
if (window.ReactNativeWebView) {
|
|
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
type: 'support_page_opened'
|
|
}));
|
|
}
|
|
|
|
if (window.flutter_inappwebview) {
|
|
window.flutter_inappwebview.callHandler('supportPageOpened');
|
|
}
|
|
</script>
|
|
{% endblock %}
|