import { fetchTicket, fetchComments, fetchHistory, createComment, formatDateTime, formatMinutes, getHistoryIcon, escapeHtml, linkify } from './ticket-shared.js'; document.addEventListener('DOMContentLoaded', () => { document.body.classList.add('user-view'); const ticketId = new URLSearchParams(window.location.search).get('id'); if (!ticketId) return (window.location.href = '/'); const ticketTitle = document.getElementById('ticket-title-text'); const ticketIdElem = document.getElementById('ticket-id-val'); const ticketStatus = document.getElementById('ticket-status-badge'); const ticketPriority = document.getElementById('priority-text'); const ticketDescription = document.getElementById('ticket-description-text'); const ticketCreated = document.getElementById('ticket-created'); const ticketUpdated = document.getElementById('ticket-updated'); const ticketCategory = document.getElementById('ticket-category'); const commentsContainer = document.getElementById('comments-container'); const historyContainer = document.getElementById('history-container'); const commentForm = document.getElementById('comment-form'); const tabBtns = document.querySelectorAll('.tab-btn'); let originalStatus = ''; let originalPriority = ''; async function loadTicketDetails() { const ticket = await fetchTicket(ticketId); if (!ticket) return alert('Ticket not found'); ticketTitle.textContent = ticket.title; ticketIdElem.textContent = ticket.id; ticketStatus.textContent = ticket.status; ticketDescription.innerHTML = linkify(ticket.description || ''); ticketCreated.textContent = formatDateTime(ticket.created_at); ticketUpdated.textContent = formatDateTime(ticket.updated_at); ticketPriority.textContent = ticket.priority; if (ticketCategory) ticketCategory.textContent = ticket.category || '—'; ticketStatus.className = `ticket-status status-${ticket.status.replace(/ /g, '-')}`; const totalTimeDisplay = document.getElementById('total-time'); if (totalTimeDisplay) totalTimeDisplay.textContent = formatMinutes(ticket.total_time || 0); originalStatus = ticket.status; originalPriority = ticket.priority; } async function loadComments() { const comments = await fetchComments(ticketId); commentsContainer.innerHTML = comments.map(comment => { const role = comment.role ? comment.role.toLowerCase() : 'user'; let avatarUrl = '/assets/user.jpg'; if (role === 'admin') avatarUrl = '/assets/admin.jpg'; return `
${role.charAt(0).toUpperCase() + role.slice(1)} Avatar
${escapeHtml(comment.author)} ${formatDateTime(comment.date)}
${linkify(comment.content)}
`; }).join(''); } async function loadHistory() { const history = await fetchHistory(ticketId); historyContainer.innerHTML = history.map(h => `
${escapeHtml(h.action)}
${escapeHtml(h.message || h.details || '')}
By ${escapeHtml(h.author || h.actor || 'unknown')} ${formatDateTime(h.date)}
`).join(''); } if (commentForm) { commentForm.addEventListener('submit', async (e) => { e.preventDefault(); const author = document.getElementById('comment-author')?.value || 'Unknown'; const content = document.getElementById('comment-content')?.value; if (!content?.trim()) return alert('Please enter a comment'); try { await createComment(ticketId, { author, content, timestamp: new Date().toISOString() }); // Webhook notification is handled server-side document.getElementById('comment-content').value = ''; await loadComments(); await loadHistory(); } catch (err) { console.error('Failed to create comment:', err); alert('Failed to submit comment. Please try again.'); } }); } async function checkForChanges() { const ticket = await fetchTicket(ticketId); if (!ticket) return; if (ticket.status !== originalStatus) { originalStatus = ticket.status; ticketStatus.textContent = ticket.status; ticketStatus.className = `ticket-status status-${ticket.status.replace(/ /g, '-')}`; } if (ticket.priority !== originalPriority) { originalPriority = ticket.priority; ticketPriority.textContent = ticket.priority; } if (ticketCategory && ticket.category !== ticketCategory.textContent) { ticketCategory.textContent = ticket.category || '—'; } } tabBtns.forEach(btn => btn.addEventListener('click', () => { tabBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active')); document.getElementById(`${btn.dataset.tab}-tab`).classList.add('active'); })); // Initial load loadTicketDetails(); loadComments(); loadHistory(); // Poll for changes every 30s setInterval(checkForChanges, 30000); });