/** * Ticket Create View * Minimal, fast form for creating new tickets. */ const TicketCreateView = { async render() { const container = document.getElementById('view-container'); container.innerHTML = '

Caricamento form...

'; try { await App.ensureLookups(); container.innerHTML = ` Torna indietro
Crea Nuovo Ticket
`; this.bindEvents(); } catch (err) { container.innerHTML = `
⚠️
Errore caricamento form
${App.escapeHtml(err.message)}
`; } }, bindEvents() { const submitBtn = document.getElementById('create-submit'); const companySearchInput = document.getElementById('create-company-search'); const customerIdInput = document.getElementById('create-customer-id'); const userSearchInput = document.getElementById('create-user-search'); const userSuggestionsDiv = document.getElementById('user-suggestions'); const customerUserIdInput = document.getElementById('create-customer-user-id'); const ownerSearchInput = document.getElementById('create-owner-search'); const ownerSuggestionsDiv = document.getElementById('owner-suggestions'); const ownerIdInput = document.getElementById('create-owner'); const responsibleSearchInput = document.getElementById('create-responsible-search'); const responsibleSuggestionsDiv = document.getElementById('responsible-suggestions'); const responsibleIdInput = document.getElementById('create-responsible'); const queueSearchInput = document.getElementById('create-queue-search'); const queueSuggestionsDiv = document.getElementById('queue-suggestions'); const queueIdInput = document.getElementById('create-queue'); const stateIdInput = document.getElementById('create-state'); const toggleBtn = document.getElementById('toggle-advanced'); const advancedOptions = document.getElementById('advanced-options'); const arrow = document.getElementById('advanced-arrow'); // Pre-populate default values asynchronously setTimeout(async () => { // 1. Owner & Responsible pre-population with active agent const currentAgentId = localStorage.getItem('activeAgentId') || '1'; const activeAgent = (App.lookups.users || []).find(u => String(u.id) === String(currentAgentId)); if (activeAgent) { if (ownerSearchInput && ownerIdInput) { ownerSearchInput.value = `${activeAgent.first_name} ${activeAgent.last_name}`; ownerIdInput.value = activeAgent.id; } if (responsibleSearchInput && responsibleIdInput) { responsibleSearchInput.value = `${activeAgent.first_name} ${activeAgent.last_name}`; responsibleIdInput.value = activeAgent.id; } } // 2. Customer User pre-population with first match try { const companies = await App.api('/api/customer-companies/search?q=cliente'); if (companies.length > 0 && customerIdInput && companySearchInput) { const defaultCompany = companies[0]; customerIdInput.value = defaultCompany.customer_id; companySearchInput.value = defaultCompany.customer_id; // Search users for this company const users = await App.api(`/api/customer-users/search?q=&customer_company_id=${encodeURIComponent(defaultCompany.customer_id)}`); if (users.length > 0 && userSearchInput && customerUserIdInput) { const defaultUser = users[0]; userSearchInput.value = `${defaultUser.first_name} ${defaultUser.last_name}`; customerUserIdInput.value = defaultUser.login; } else { // Fallback: use company name as customer user ID userSearchInput.value = defaultCompany.name; customerUserIdInput.value = defaultCompany.customer_id; } } } catch (err) { console.error('Error pre-populating defaults:', err); } // 3. Queue pre-population try { const queues = await App.api('/api/queues/search?q='); if (queues.length > 0 && queueSearchInput && queueIdInput) { queueSearchInput.value = queues[0].name; queueIdInput.value = queues[0].id; } } catch (err) { console.error('Error pre-populating queues:', err); } }, 50); // Collapsible Options Toggle if (toggleBtn && advancedOptions && arrow) { toggleBtn.addEventListener('click', () => { const isHidden = advancedOptions.style.display === 'none'; advancedOptions.style.display = isHidden ? 'grid' : 'none'; arrow.style.transform = isHidden ? 'rotate(90deg)' : 'rotate(0deg)'; }); } // User Autocomplete let userDebounce; if (userSearchInput) { userSearchInput.addEventListener('input', () => { clearTimeout(userDebounce); const q = userSearchInput.value.trim(); if (q.length < 2) { userSuggestionsDiv.style.display = 'none'; customerUserIdInput.value = ''; return; } userDebounce = setTimeout(async () => { try { const users = await App.api(`/api/customer-users/search?q=${encodeURIComponent(q)}`); if (users.length === 0) { userSuggestionsDiv.innerHTML = '
Nessun utente trovato
'; userSuggestionsDiv.style.display = 'block'; return; } userSuggestionsDiv.innerHTML = users.map(u => `
${App.escapeHtml(u.first_name)} ${App.escapeHtml(u.last_name)} (Login: ${App.escapeHtml(u.login)} | Azienda: ${App.escapeHtml(u.customer_id || '—')})
`).join(''); userSuggestionsDiv.style.display = 'block'; // Bind click userSuggestionsDiv.querySelectorAll('.autocomplete-suggestion-item').forEach(item => { if (item.dataset.login) { item.addEventListener('click', () => { userSearchInput.value = item.dataset.name; customerUserIdInput.value = item.dataset.login; userSuggestionsDiv.style.display = 'none'; // Auto-fill company inside Advanced Options if (item.dataset.customerId) { customerIdInput.value = item.dataset.customerId; companySearchInput.value = item.dataset.customerId; } }); } }); } catch (err) { console.error(err); } }, 300); }); } // Owner Autocomplete (dynamic backend search) let ownerDebounce; if (ownerSearchInput) { ownerSearchInput.addEventListener('input', () => { clearTimeout(ownerDebounce); const q = ownerSearchInput.value.trim(); // Do not block empty query to allow all agent results on focus ownerDebounce = setTimeout(async () => { try { const agents = await App.api(`/api/agents/search?q=${encodeURIComponent(q)}`); if (agents.length === 0) { ownerSuggestionsDiv.innerHTML = '
Nessun agente trovato
'; ownerSuggestionsDiv.style.display = 'block'; return; } ownerSuggestionsDiv.innerHTML = agents.map(u => `
${App.escapeHtml(u.first_name)} ${App.escapeHtml(u.last_name)} (Login: ${App.escapeHtml(u.login)})
`).join(''); ownerSuggestionsDiv.style.display = 'block'; // Bind click ownerSuggestionsDiv.querySelectorAll('.autocomplete-suggestion-item').forEach(item => { if (item.dataset.id) { item.addEventListener('click', () => { ownerSearchInput.value = item.dataset.name; ownerIdInput.value = item.dataset.id; ownerSuggestionsDiv.style.display = 'none'; }); } }); } catch (err) { console.error(err); } }, 300); }); ownerSearchInput.addEventListener('focus', () => { ownerSearchInput.value = ''; ownerIdInput.value = ''; ownerSearchInput.dispatchEvent(new Event('input')); }); } // Responsible Autocomplete (dynamic backend search) let responsibleDebounce; if (responsibleSearchInput) { responsibleSearchInput.addEventListener('input', () => { clearTimeout(responsibleDebounce); const q = responsibleSearchInput.value.trim(); // Do not block empty query to allow all agent results on focus responsibleDebounce = setTimeout(async () => { try { const agents = await App.api(`/api/agents/search?q=${encodeURIComponent(q)}`); if (agents.length === 0) { responsibleSuggestionsDiv.innerHTML = '
Nessun agente trovato
'; responsibleSuggestionsDiv.style.display = 'block'; return; } responsibleSuggestionsDiv.innerHTML = agents.map(u => `
${App.escapeHtml(u.first_name)} ${App.escapeHtml(u.last_name)} (Login: ${App.escapeHtml(u.login)})
`).join(''); responsibleSuggestionsDiv.style.display = 'block'; // Bind click responsibleSuggestionsDiv.querySelectorAll('.autocomplete-suggestion-item').forEach(item => { if (item.dataset.id) { item.addEventListener('click', () => { responsibleSearchInput.value = item.dataset.name; responsibleIdInput.value = item.dataset.id; responsibleSuggestionsDiv.style.display = 'none'; }); } }); } catch (err) { console.error(err); } }, 300); }); responsibleSearchInput.addEventListener('focus', () => { responsibleSearchInput.value = ''; responsibleIdInput.value = ''; responsibleSearchInput.dispatchEvent(new Event('input')); }); } // Queue Autocomplete let queueDebounce; if (queueSearchInput) { queueSearchInput.addEventListener('input', () => { clearTimeout(queueDebounce); const q = queueSearchInput.value.trim(); queueDebounce = setTimeout(async () => { try { const queues = await App.api(`/api/queues/search?q=${encodeURIComponent(q)}`); if (queues.length === 0) { queueSuggestionsDiv.innerHTML = '
Nessuna coda trovata
'; queueSuggestionsDiv.style.display = 'block'; return; } queueSuggestionsDiv.innerHTML = queues.map(q => `
${App.escapeHtml(q.name)}
`).join(''); queueSuggestionsDiv.style.display = 'block'; // Bind click queueSuggestionsDiv.querySelectorAll('.autocomplete-suggestion-item').forEach(item => { if (item.dataset.id) { item.addEventListener('click', () => { queueSearchInput.value = item.dataset.name; queueIdInput.value = item.dataset.id; queueSuggestionsDiv.style.display = 'none'; }); } }); } catch (err) { console.error(err); } }, 150); }); queueSearchInput.addEventListener('focus', () => { queueSearchInput.value = ''; queueIdInput.value = ''; queueSearchInput.dispatchEvent(new Event('input')); }); } // Close suggestions on click outside document.addEventListener('click', (e) => { if (userSearchInput && e.target !== userSearchInput && e.target !== userSuggestionsDiv) { userSuggestionsDiv.style.display = 'none'; } if (ownerSearchInput && e.target !== ownerSearchInput && e.target !== ownerSuggestionsDiv) { ownerSuggestionsDiv.style.display = 'none'; } if (responsibleSearchInput && e.target !== responsibleSearchInput && e.target !== responsibleSuggestionsDiv) { responsibleSuggestionsDiv.style.display = 'none'; } if (queueSearchInput && e.target !== queueSearchInput && e.target !== queueSuggestionsDiv) { queueSuggestionsDiv.style.display = 'none'; } }); submitBtn.addEventListener('click', async () => { const title = document.getElementById('create-title').value.trim(); const queue_id = queueIdInput.value; const state_id = stateIdInput.value; const priority_id = document.getElementById('create-priority').value; const type_id = document.getElementById('create-type')?.value; const customerId = customerIdInput.value; let customerUserId = customerUserIdInput.value; const ownerId = ownerIdInput.value; const responsibleId = responsibleIdInput.value; // Validation if (!title) { Toast.warning('Il titolo è obbligatorio'); document.getElementById('create-title').focus(); return; } if (!queue_id) { Toast.warning('Seleziona una coda'); queueSearchInput.focus(); return; } if (!state_id) { Toast.warning('Seleziona uno stato'); document.getElementById('create-state').focus(); return; } if (!customerId && !customerUserId) { Toast.warning('Seleziona un Utente Cliente'); userSearchInput.focus(); return; } // Company fallback if no individual user selected if (customerId && !customerUserId) { customerUserId = customerId; } const payload = { title, queue_id: parseInt(queue_id), state_id: parseInt(state_id), priority_id: parseInt(priority_id), user_id: ownerId ? parseInt(ownerId) : undefined, responsible_user_id: responsibleId ? parseInt(responsibleId) : undefined, type_id: type_id ? parseInt(type_id) : undefined, customer_id: customerId || undefined, customer_user_id: customerUserId || undefined, subject: document.getElementById('create-subject').value.trim() || undefined, body: document.getElementById('create-body').value.trim() || undefined, }; try { submitBtn.disabled = true; submitBtn.innerHTML = '
Creazione...'; const result = await App.api('/api/tickets', { method: 'POST', body: JSON.stringify(payload), }); Toast.success(`Ticket #${result.tn} creato!`); // Navigate to the new ticket window.location.hash = `#/tickets/${result.id}`; } catch (err) { Toast.error('Errore creazione: ' + err.message); submitBtn.disabled = false; submitBtn.innerHTML = ` Crea Ticket `; } }); }, };