// actions.js — wires up all action buttons on the asset card import { updateAsset, getContacts } from '../api/syncro.js'; import { showToast } from './toast.js'; import { resetIdleTimer, focusScanInput } from './scanner.js'; import { renderAssetCard } from './assetCard.js'; import { updateCachedAsset, getCustomerContacts } from './assetBrowser.js'; import { initTicketHistory } from './ticketHistory.js'; import { addToQueueAndOpen } from './labelCenter.js'; import { addToQueue } from './labelCenter.js'; let _asset = null; let _contacts = null; let _pendingAction = null; // 'change-owner' | 'sign-out' export function initActions(asset) { _asset = asset; _contacts = null; _pendingAction = null; // Possession toggle document.getElementById('action-toggle-possession')?.addEventListener('click', handleTogglePossession); // Lifecycle dropdown toggle document.getElementById('action-lifecycle')?.addEventListener('click', handleLifecycleClick); // Change owner document.getElementById('action-change-owner')?.addEventListener('click', () => openContactPanel('change-owner')); // Remove user document.getElementById('action-remove-user')?.addEventListener('click', handleRemoveUser); // Sign out document.getElementById('action-sign-out')?.addEventListener('click', () => openContactPanel('sign-out')); // Print label document.getElementById('action-print-label')?.addEventListener('click', () => addToQueueAndOpen(_asset)); // Add to Label Center queue document.getElementById('action-add-to-queue')?.addEventListener('click', () => addToQueue(_asset)); // Lifecycle dropdown options (action section) document.querySelectorAll('.lifecycle-option').forEach(btn => { btn.addEventListener('click', () => handleSetLifecycle(btn.dataset.stage)); }); // Status badge dropdowns (status section) document.getElementById('status-possession-btn')?.addEventListener('click', _handleStatusPossessionClick); document.getElementById('status-lifecycle-btn')?.addEventListener('click', _handleStatusLifecycleClick); document.querySelectorAll('.status-dropdown-option[data-possession]').forEach(btn => { btn.addEventListener('click', () => _handleSetPossession(btn.dataset.possession)); }); document.querySelectorAll('#status-lifecycle-dropdown .status-dropdown-option[data-stage]').forEach(btn => { btn.addEventListener('click', () => _handleSetLifecycleFromStatus(btn.dataset.stage)); }); // Close dropdowns when clicking outside document.addEventListener('click', _handleOutsideClick, { capture: true }); // Contact panel document.getElementById('contact-cancel')?.addEventListener('click', closeContactPanel); document.getElementById('contact-search')?.addEventListener('input', filterContacts); // Infrastructure document.getElementById('action-infrastructure')?.addEventListener('click', _openInfraPanel); document.getElementById('infra-cancel-btn')?.addEventListener('click', _closeInfraPanel); document.getElementById('infra-confirm-btn')?.addEventListener('click', _handleConfirmInfra); document.getElementById('infra-tag-input')?.addEventListener('keydown', e => { if (e.key === 'Enter') document.getElementById('infra-location-input')?.focus(); }); document.getElementById('infra-location-input')?.addEventListener('keydown', e => { if (e.key === 'Enter') _handleConfirmInfra(); }); } // ── Toggle Possession ───────────────────────────────────────────────────────── async function handleTogglePossession() { const btn = document.getElementById('action-toggle-possession'); const current = _asset?.properties?.['Possession Status']; const next = current === 'In IT Possession' ? 'Deployed' : 'In IT Possession'; const actionDesc = `Possession toggled to ${next}`; setButtonLoading(btn, true); try { const newHistory = appendHistory(_asset.properties?.['Asset History'], actionDesc); await updateAsset(_asset.id, { properties: { 'Possession Status': next, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory, }, }, _asset.customer_id); _asset.properties = { ...(_asset.properties ?? {}), 'Possession Status': next, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory }; refreshCard(); showToast(`Possession set to: ${next}`, 'success'); } catch (err) { showToast('Failed: ' + err.message, 'error'); } finally { resetIdleTimer(); } } // ── Lifecycle Stage ─────────────────────────────────────────────────────────── function handleLifecycleClick(e) { e.stopPropagation(); const btn = document.getElementById('action-lifecycle'); const dropdown = document.getElementById('lifecycle-dropdown'); const isOpen = dropdown?.classList.contains('open'); _closeLifecycleDropdown(); if (!isOpen) { dropdown?.classList.add('open'); btn?.classList.add('open'); } } function _closeLifecycleDropdown() { document.getElementById('lifecycle-dropdown')?.classList.remove('open'); document.getElementById('action-lifecycle')?.classList.remove('open'); } function _handleOutsideClick(e) { const wrap = document.querySelector('.lc-wrap'); if (wrap && !wrap.contains(e.target)) { _closeLifecycleDropdown(); } if (!e.target.closest('.status-badge-wrap')) { _closeAllStatusDropdowns(); } } // ── Status Badge Dropdowns ──────────────────────────────────────────────────── function _handleStatusPossessionClick(e) { e.stopPropagation(); const btn = document.getElementById('status-possession-btn'); const dropdown = document.getElementById('status-possession-dropdown'); const isOpen = dropdown?.classList.contains('open'); _closeAllStatusDropdowns(); if (!isOpen) { dropdown?.classList.add('open'); btn?.classList.add('open'); } } function _handleStatusLifecycleClick(e) { e.stopPropagation(); const btn = document.getElementById('status-lifecycle-btn'); const dropdown = document.getElementById('status-lifecycle-dropdown'); const isOpen = dropdown?.classList.contains('open'); _closeAllStatusDropdowns(); if (!isOpen) { dropdown?.classList.add('open'); btn?.classList.add('open'); } } function _closePossessionStatusDropdown() { document.getElementById('status-possession-dropdown')?.classList.remove('open'); document.getElementById('status-possession-btn')?.classList.remove('open'); } function _closeLifecycleStatusDropdown() { document.getElementById('status-lifecycle-dropdown')?.classList.remove('open'); document.getElementById('status-lifecycle-btn')?.classList.remove('open'); } function _closeAllStatusDropdowns() { _closePossessionStatusDropdown(); _closeLifecycleStatusDropdown(); } async function _handleSetPossession(next) { _closePossessionStatusDropdown(); const actionDesc = `Possession toggled to ${next}`; try { const newHistory = appendHistory(_asset.properties?.['Asset History'], actionDesc); await updateAsset(_asset.id, { properties: { 'Possession Status': next, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory, }, }, _asset.customer_id); _asset.properties = { ...(_asset.properties ?? {}), 'Possession Status': next, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory }; refreshCard(); showToast(`Possession set to: ${next}`, 'success'); } catch (err) { showToast('Failed: ' + err.message, 'error'); } finally { resetIdleTimer(); } } async function _handleSetLifecycleFromStatus(stage) { _closeLifecycleStatusDropdown(); const actionDesc = `Lifecycle moved to ${stage}`; try { const newHistory = appendHistory(_asset.properties?.['Asset History'], actionDesc); await updateAsset(_asset.id, { properties: { 'Lifecycle Stage': stage, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory, }, }, _asset.customer_id); _asset.properties = { ...(_asset.properties ?? {}), 'Lifecycle Stage': stage, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory }; refreshCard(); showToast(`Lifecycle stage: ${stage}`, 'success'); } catch (err) { showToast('Failed: ' + err.message, 'error'); } finally { resetIdleTimer(); } } async function handleSetLifecycle(stage) { _closeLifecycleDropdown(); const actionDesc = `Lifecycle moved to ${stage}`; try { const newHistory = appendHistory(_asset.properties?.['Asset History'], actionDesc); await updateAsset(_asset.id, { properties: { 'Lifecycle Stage': stage, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory, }, }, _asset.customer_id); _asset.properties = { ...(_asset.properties ?? {}), 'Lifecycle Stage': stage, 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory }; refreshCard(); showToast(`Lifecycle stage: ${stage}`, 'success'); } catch (err) { showToast('Failed: ' + err.message, 'error'); } finally { resetIdleTimer(); } } // ── Remove User ─────────────────────────────────────────────────────────────── async function handleRemoveUser() { const actionDesc = `User removed`; const newHistory = appendHistory(_asset.properties?.['Asset History'], actionDesc); try { await updateAsset(_asset.id, { contact_id: null, properties: { 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory, }, }, _asset.customer_id); _asset.contact_id = null; _asset.contact = null; _asset.contact_fullname = null; _asset.properties = { ...(_asset.properties ?? {}), 'Last Scan Date': today(), 'Last Action': actionDesc, 'Asset History': newHistory }; refreshCard(); showToast('User removed', 'success'); } catch (err) { showToast('Failed: ' + err.message, 'error'); } finally { resetIdleTimer(); } } // ── Contact Panel ───────────────────────────────────────────────────────────── async function openContactPanel(action) { _pendingAction = action; const panel = document.getElementById('contact-panel'); const titleEl = document.getElementById('contact-panel-title'); const listEl = document.getElementById('contact-list'); const searchEl = document.getElementById('contact-search'); titleEl.textContent = action === 'sign-out' ? 'Sign Out — Select Employee' : 'Change User — Select Contact'; searchEl.value = ''; panel.classList.add('visible'); panel.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); // Close lifecycle dropdown if open _closeLifecycleDropdown(); if (_contacts) { renderContactList(listEl, _contacts); return; } // Use the browser-side contact cache if warm (avoids spinner on repeat opens) const cached = getCustomerContacts(_asset.customer_id); if (cached) { _contacts = cached; renderContactList(listEl, _contacts); return; } listEl.innerHTML = `