// ticketHistory.js — fetches recent tickets and renders them into the card. // Filters to tickets belonging to the asset's assigned contact. // Falls back to the 5 most recent customer tickets if no contact is assigned // or if the contact has no tickets. import { getTickets } from '../api/syncro.js'; let _loaded = false; let _open = false; export function initTicketHistory(asset) { _loaded = false; _open = false; const toggle = document.getElementById('ticket-toggle'); const list = document.getElementById('ticket-list'); if (!toggle || !list) return; toggle.classList.remove('open'); list.classList.remove('visible'); list.innerHTML = `
${spinnerHTML()} Loading tickets…
`; toggle.onclick = async () => { _open = !_open; toggle.classList.toggle('open', _open); list.classList.toggle('visible', _open); if (_open && !_loaded) { await loadTickets(list, asset.customer_id, asset.contact_id ?? null); _loaded = true; } }; // Wire up asset history toggle (static content, no async load needed) const historyToggle = document.getElementById('history-toggle'); const historyList = document.getElementById('history-list'); if (historyToggle && historyList) { let historyOpen = false; historyToggle.classList.remove('open'); historyList.classList.remove('visible'); historyToggle.onclick = () => { historyOpen = !historyOpen; historyToggle.classList.toggle('open', historyOpen); historyList.classList.toggle('visible', historyOpen); }; } } async function loadTickets(listEl, customerId, contactId) { listEl.innerHTML = `
${spinnerHTML()} Loading tickets…
`; try { const all = await getTickets(customerId); let tickets; let scopeLabel; if (contactId) { const contactMatches = all.filter(t => t.contact_id === contactId); if (contactMatches.length > 0) { tickets = contactMatches.slice(0, 10); scopeLabel = null; // no label needed — these are contact-scoped } else { // Contact exists but has no tickets — fall back to recent customer tickets tickets = all.slice(0, 5); scopeLabel = 'No tickets for assigned contact — showing recent customer tickets'; } } else { tickets = all.slice(0, 5); scopeLabel = 'No contact assigned — showing recent customer tickets'; } if (!tickets.length) { listEl.innerHTML = `
No tickets found.
`; return; } listEl.innerHTML = (scopeLabel ? `
${esc(scopeLabel)}
` : '') + tickets.map(t => ticketItemHTML(t)).join(''); } catch (err) { listEl.innerHTML = `
Failed to load tickets: ${esc(err.message)}
`; } } function ticketItemHTML(t) { const statusKey = (t.status ?? '').toLowerCase().replace(/\s+/g, '-'); const date = t.created_at ? new Date(t.created_at).toLocaleDateString('en-US', { month:'short', day:'numeric', year:'numeric' }) : ''; const contactName = t.contact_fullname ? ` · ${esc(t.contact_fullname)}` : ''; return `
${esc(t.subject ?? t.problem_type ?? 'Ticket #' + (t.number ?? t.id))}
#${t.number ?? t.id} · ${date}${contactName}
${esc(t.status ?? 'Unknown')}
`; } function spinnerHTML() { return ``; } function esc(s) { return String(s ?? '').replace(/&/g,'&').replace(//g,'>'); }