// 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,'>');
}