Files
delphi-database/templates/support_modal.html
HotSwapp c2f3c4411d progress
2025-08-09 16:37:57 -05:00

384 lines
20 KiB
HTML

<!-- Support Ticket Modal -->
<div id="supportModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div class="bg-white dark:bg-neutral-800 rounded-xl shadow-xl max-w-4xl w-full max-h-screen overflow-hidden">
<div class="flex items-center justify-between px-6 py-4 bg-primary-600 text-white">
<h2 class="text-xl font-semibold flex items-center gap-2">
<i class="fas fa-bug"></i>
<span>Submit Internal Issue</span>
</h2>
<button onclick="closeSupportModal()" class="text-primary-200 hover:text-white transition-colors">
<i class="fa-solid fa-xmark text-xl"></i>
</button>
</div>
<div class="px-6 py-4 max-h-96 overflow-y-auto scrollbar-thin">
<form id="supportForm">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label for="contactName" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-2">Reporter Name *</label>
<input type="text" id="contactName" required class="w-full px-3 py-2 bg-white dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-600 rounded-lg text-neutral-900 dark:text-neutral-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200">
</div>
<div>
<label for="contactEmail" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-2">Reporter Email *</label>
<input type="email" id="contactEmail" required class="w-full px-3 py-2 bg-white dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-600 rounded-lg text-neutral-900 dark:text-neutral-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200">
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label for="ticketCategory" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-2">Issue Type *</label>
<select id="ticketCategory" required class="w-full px-3 py-2 bg-white dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-600 rounded-lg text-neutral-900 dark:text-neutral-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200">
<option value="">Select issue type...</option>
<option value="bug_report" selected>Bug Report</option>
<option value="qa_issue">QA Issue</option>
<option value="feature_request">Feature Request</option>
<option value="database_issue">Database Issue</option>
<option value="system_error">System Error</option>
<option value="user_access">User Access</option>
<option value="performance">Performance Issue</option>
<option value="documentation">Documentation</option>
<option value="configuration">Configuration</option>
<option value="testing">Testing Request</option>
</select>
</div>
<div>
<label for="ticketPriority" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-2">Priority</label>
<select id="ticketPriority" class="w-full px-3 py-2 bg-white dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-600 rounded-lg text-neutral-900 dark:text-neutral-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200">
<option value="low">Low</option>
<option value="medium" selected>Medium</option>
<option value="high">High</option>
<option value="urgent">Urgent</option>
</select>
</div>
</div>
<div class="mb-4">
<label for="ticketSubject" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-2">Issue Summary *</label>
<input type="text" id="ticketSubject" maxlength="200" required class="w-full px-3 py-2 bg-white dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-600 rounded-lg text-neutral-900 dark:text-neutral-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200">
<p class="text-sm text-neutral-500 dark:text-neutral-400 mt-1">Brief summary of the bug/issue</p>
</div>
<div class="mb-4">
<label for="ticketDescription" class="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-2">Detailed Description *</label>
<textarea id="ticketDescription" rows="5" required class="w-full px-3 py-2 bg-white dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-600 rounded-lg text-neutral-900 dark:text-neutral-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200 resize-none" placeholder="Steps to reproduce:
1.
2.
3.
Expected behavior:
Actual behavior:
Additional context:"></textarea>
<p class="text-sm text-neutral-500 dark:text-neutral-400 mt-1">Include steps to reproduce, expected vs actual behavior, error messages, etc.</p>
</div>
<!-- System Information -->
<div class="bg-neutral-50 dark:bg-neutral-800/50 rounded-lg border border-neutral-200 dark:border-neutral-700 p-4 mb-4">
<h3 class="text-sm font-semibold text-neutral-700 dark:text-neutral-300 mb-3 flex items-center gap-2">
<i class="fas fa-info-circle text-info-600"></i>
<span>System Information</span>
<span class="text-xs font-normal text-neutral-500 dark:text-neutral-400">(automatically included)</span>
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
<div>
<span class="font-medium text-neutral-600 dark:text-neutral-400">Current Page:</span>
<span id="currentPageInfo" class="text-neutral-900 dark:text-neutral-100 ml-1">Loading...</span>
</div>
<div>
<span class="font-medium text-neutral-600 dark:text-neutral-400">Browser:</span>
<span id="browserInfo" class="text-neutral-900 dark:text-neutral-100 ml-1">Loading...</span>
</div>
</div>
</div>
<div class="flex items-start gap-3 p-4 bg-info-50 dark:bg-info-900/20 border border-info-200 dark:border-info-800 rounded-lg text-info-800 dark:text-info-300">
<i class="fas fa-info-circle text-info-600 dark:text-info-400 mt-0.5"></i>
<div>
<p class="font-medium">Note:</p>
<p class="text-sm mt-1">Your issue will be assigned a tracking number and the development team will be notified automatically.</p>
</div>
</div>
</form>
</div>
<div class="flex items-center justify-end gap-3 px-6 py-4 border-t border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800/50">
<button onclick="closeSupportModal()" class="px-4 py-2 bg-neutral-100 dark:bg-neutral-700 text-neutral-700 dark:text-neutral-300 hover:bg-neutral-200 dark:hover:bg-neutral-600 rounded-lg transition-colors duration-200">
Cancel
</button>
<button type="button" id="submitSupportTicket" class="flex items-center gap-2 px-4 py-2 bg-primary-600 text-white hover:bg-primary-700 rounded-lg transition-colors duration-200">
<i class="fas fa-bug"></i>
<span>Submit Issue</span>
</button>
</div>
</div>
</div>
<!-- Support Ticket Success Modal -->
<div id="supportSuccessModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div class="bg-white dark:bg-neutral-800 rounded-xl shadow-xl max-w-2xl w-full">
<div class="flex items-center justify-between px-6 py-4 bg-success-600 text-white">
<h2 class="text-xl font-semibold flex items-center gap-2">
<i class="fas fa-check-circle"></i>
<span>Issue Submitted Successfully</span>
</h2>
<button onclick="closeSupportSuccessModal()" class="text-success-200 hover:text-white transition-colors">
<i class="fa-solid fa-xmark text-xl"></i>
</button>
</div>
<div class="px-6 py-8 text-center">
<div class="mb-6">
<div class="w-16 h-16 bg-success-100 dark:bg-success-900/30 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="fas fa-bug text-2xl text-success-600 dark:text-success-400"></i>
</div>
<h3 class="text-xl font-semibold text-neutral-900 dark:text-neutral-100 mb-2">Issue logged successfully!</h3>
</div>
<div class="bg-success-50 dark:bg-success-900/20 border border-success-200 dark:border-success-800 rounded-lg p-4 mb-6">
<div class="flex items-center justify-center gap-2">
<span class="font-medium text-success-800 dark:text-success-300">Issue ID:</span>
<span id="newTicketNumber" class="font-mono font-semibold text-success-900 dark:text-success-200"></span>
</div>
</div>
<p class="text-neutral-600 dark:text-neutral-400 mb-6">
Your issue has been logged and the development team has been notified. You'll receive updates on the resolution progress.
</p>
<div class="text-left">
<h4 class="text-lg font-semibold text-neutral-900 dark:text-neutral-100 mb-4 text-center">What happens next?</h4>
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-success-100 dark:bg-success-900/30 rounded-full flex items-center justify-center flex-shrink-0">
<i class="fas fa-check text-success-600 dark:text-success-400 text-sm"></i>
</div>
<span class="text-neutral-700 dark:text-neutral-300">Issue logged in tracking system</span>
</div>
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-warning-100 dark:bg-warning-900/30 rounded-full flex items-center justify-center flex-shrink-0">
<i class="fas fa-users text-warning-600 dark:text-warning-400 text-sm"></i>
</div>
<span class="text-neutral-700 dark:text-neutral-300">Development team has been notified</span>
</div>
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-info-100 dark:bg-info-900/30 rounded-full flex items-center justify-center flex-shrink-0">
<i class="fas fa-code text-info-600 dark:text-info-400 text-sm"></i>
</div>
<span class="text-neutral-700 dark:text-neutral-300">Issue will be triaged and prioritized</span>
</div>
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-primary-100 dark:bg-primary-900/30 rounded-full flex items-center justify-center flex-shrink-0">
<i class="fas fa-bell text-primary-600 dark:text-primary-400 text-sm"></i>
</div>
<span class="text-neutral-700 dark:text-neutral-300">You'll get status updates via email</span>
</div>
</div>
</div>
</div>
<div class="flex items-center justify-end gap-3 px-6 py-4 border-t border-neutral-200 dark:border-neutral-700 bg-neutral-50 dark:bg-neutral-800/50">
<button onclick="closeSupportSuccessModal()" class="px-4 py-2 bg-success-600 text-white hover:bg-success-700 rounded-lg transition-colors duration-200">
Close
</button>
</div>
</div>
</div>
<script>
// Support ticket functionality - Tailwind version
let supportSystem = {
currentPageInfo: 'Unknown',
browserInfo: 'Unknown',
init: function() {
this.detectSystemInfo();
this.setupEventListeners();
},
detectSystemInfo: function() {
// Get current page information
const path = window.location.pathname;
const pageNames = {
'/': 'Dashboard',
'/login': 'Login Page',
'/customers': 'Customer Management',
'/files': 'File Cabinet',
'/financial': 'Financial/Ledger',
'/documents': 'Document Management',
'/import': 'Data Import',
'/search': 'Advanced Search',
'/admin': 'System Administration'
};
this.currentPageInfo = pageNames[path] || `Page: ${path}`;
// Get browser information
const userAgent = navigator.userAgent;
let browserName = 'Unknown';
if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) {
browserName = 'Chrome';
} else if (userAgent.includes('Firefox')) {
browserName = 'Firefox';
} else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
browserName = 'Safari';
} else if (userAgent.includes('Edg')) {
browserName = 'Edge';
}
this.browserInfo = `${browserName} (${navigator.platform})`;
// Update modal display
const currentPageElement = document.getElementById('currentPageInfo');
const browserElement = document.getElementById('browserInfo');
if (currentPageElement) currentPageElement.textContent = this.currentPageInfo;
if (browserElement) browserElement.textContent = this.browserInfo;
},
setupEventListeners: function() {
// Submit button
const submitBtn = document.getElementById('submitSupportTicket');
if (submitBtn) {
submitBtn.addEventListener('click', this.submitTicket.bind(this));
}
// Form validation
const form = document.getElementById('supportForm');
if (form) {
form.addEventListener('submit', function(e) {
e.preventDefault();
supportSystem.submitTicket();
});
}
},
populateUserInfo: function() {
// Try to get current user info from the global app state
if (window.app && window.app.user) {
const user = window.app.user;
const nameInput = document.getElementById('contactName');
const emailInput = document.getElementById('contactEmail');
if (nameInput && !nameInput.value) {
nameInput.value = `${user.first_name || ''} ${user.last_name || ''}`.trim() || user.username;
}
if (emailInput && !emailInput.value) {
emailInput.value = user.email;
}
}
},
submitTicket: async function() {
const form = document.getElementById('supportForm');
if (!form.checkValidity()) {
// Show validation errors
form.reportValidity();
return;
}
const submitBtn = document.getElementById('submitSupportTicket');
const originalHTML = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner animate-spin"></i><span class="ml-2">Submitting...</span>';
submitBtn.disabled = true;
try {
const ticketData = {
contact_name: document.getElementById('contactName').value,
contact_email: document.getElementById('contactEmail').value,
category: document.getElementById('ticketCategory').value,
priority: document.getElementById('ticketPriority').value,
subject: document.getElementById('ticketSubject').value,
description: document.getElementById('ticketDescription').value,
current_page: this.currentPageInfo,
browser_info: this.browserInfo
};
const response = await fetch('/api/support/tickets', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(ticketData)
});
const result = await response.json();
if (response.ok) {
// Hide support modal
closeSupportModal();
// Show success modal
document.getElementById('newTicketNumber').textContent = result.ticket_number;
document.getElementById('supportSuccessModal').classList.remove('hidden');
// Reset form
form.reset();
} else {
throw new Error(result.detail || 'Failed to submit ticket');
}
} catch (error) {
console.error('Error submitting support ticket:', error);
this.showAlert('Failed to submit support ticket: ' + error.message, 'danger');
} finally {
submitBtn.innerHTML = originalHTML;
submitBtn.disabled = false;
}
},
showAlert: function(message, type = 'info') {
// Use existing alert system if available
if (window.showAlert) {
window.showAlert(message, type);
} else {
alert(message);
}
}
};
// Modal control functions
function openSupportModal() {
supportSystem.populateUserInfo();
document.getElementById('supportModal').classList.remove('hidden');
}
function closeSupportModal() {
document.getElementById('supportModal').classList.add('hidden');
}
function closeSupportSuccessModal() {
document.getElementById('supportSuccessModal').classList.add('hidden');
}
// Close modals when clicking outside
document.addEventListener('click', function(event) {
const supportModal = document.getElementById('supportModal');
const successModal = document.getElementById('supportSuccessModal');
if (event.target === supportModal) {
closeSupportModal();
}
if (event.target === successModal) {
closeSupportSuccessModal();
}
});
// Handle escape key for modals
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
closeSupportModal();
closeSupportSuccessModal();
}
});
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
supportSystem.init();
});
// Make function globally available
window.openSupportModal = openSupportModal;
</script>