381 lines
19 KiB
HTML
381 lines
19 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 window.http.wrappedFetch('/api/support/tickets', {
|
|
method: 'POST',
|
|
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> |