feat: aggiunta possiblità di modificare il cliente

This commit is contained in:
2026-07-07 08:14:07 +02:00
parent 0f012816ea
commit b3570d6757
3 changed files with 124 additions and 27 deletions
+100 -13
View File
@@ -40,6 +40,10 @@ const TicketDetailView = {
queue_id: ticket.queue_id,
user_id: ticket.user_id,
type_id: ticket.type_id,
customer_id: ticket.customer_id,
customer_user_id: ticket.customer_user_id,
customer_first: ticket.customer_first,
customer_last: ticket.customer_last,
};
container.innerHTML = `
@@ -113,6 +117,13 @@ const TicketDetailView = {
</select>
</div>
` : ''}
<div class="quick-edit-field" style="position:relative;">
<label class="quick-edit-label">Utente Cliente</label>
<input type="text" class="form-input" id="qe-customer-search" placeholder="Cerca cliente..." autocomplete="off" value="${ticket.customer_first ? `${ticket.customer_first} ${ticket.customer_last}` : (ticket.customer_user_id || '')}" style="padding: 6px 12px; height: 32px; font-size: 0.85rem;" />
<input type="hidden" id="qe-customer-user-id" data-field="customer_user_id" value="${ticket.customer_user_id || ''}" />
<input type="hidden" id="qe-customer-id" data-field="customer_id" value="${ticket.customer_id || ''}" />
<div id="qe-customer-suggestions" class="autocomplete-suggestions" style="display:none; top: 100%;"></div>
</div>
</div>
<div style="margin-top:var(--space-md);display:flex;gap:var(--space-sm);justify-content:flex-end;">
<button class="btn btn-ghost btn-sm" id="qe-reset">Reset</button>
@@ -340,41 +351,117 @@ const TicketDetailView = {
bindEvents() {
// Quick-edit change detection
const selects = document.querySelectorAll('.quick-edit-select');
const fields = document.querySelectorAll('.quick-edit-select, #qe-customer-user-id, #qe-customer-id');
const saveBtn = document.getElementById('qe-save');
const resetBtn = document.getElementById('qe-reset');
const checkChanges = () => {
let hasChanges = false;
selects.forEach(sel => {
const field = sel.dataset.field;
fields.forEach(el => {
const field = el.dataset.field;
const original = String(this.originalValues[field] || '');
const current = sel.value;
const current = el.value;
const changed = current !== original;
sel.classList.toggle('changed', changed);
el.classList.toggle('changed', changed);
if (changed) hasChanges = true;
});
saveBtn.disabled = !hasChanges;
};
selects.forEach(sel => sel.addEventListener('change', checkChanges));
fields.forEach(el => el.addEventListener('change', checkChanges));
// Customer User Autocomplete inside Quick Edit
const customerSearchInput = document.getElementById('qe-customer-search');
const customerSuggestionsDiv = document.getElementById('qe-customer-suggestions');
const customerUserIdInput = document.getElementById('qe-customer-user-id');
const customerIdInput = document.getElementById('qe-customer-id');
let customerDebounce;
if (customerSearchInput) {
customerSearchInput.addEventListener('input', () => {
clearTimeout(customerDebounce);
const q = customerSearchInput.value.trim();
if (q.length < 2) {
customerSuggestionsDiv.style.display = 'none';
customerUserIdInput.value = '';
customerIdInput.value = '';
customerUserIdInput.dispatchEvent(new Event('change'));
customerIdInput.dispatchEvent(new Event('change'));
return;
}
customerDebounce = setTimeout(async () => {
try {
const users = await App.api(`/api/customer-users/search?q=${encodeURIComponent(q)}`);
if (users.length === 0) {
customerSuggestionsDiv.innerHTML = '<div class="autocomplete-suggestion-item" style="color:var(--text-muted); cursor:default;">Nessun utente trovato</div>';
customerSuggestionsDiv.style.display = 'block';
return;
}
customerSuggestionsDiv.innerHTML = users.map(u => `
<div class="autocomplete-suggestion-item" data-login="${App.escapeHtml(u.login)}" data-customer-id="${App.escapeHtml(u.customer_id || '')}" data-name="${App.escapeHtml(u.first_name + ' ' + u.last_name)}">
<strong>${App.escapeHtml(u.first_name)} ${App.escapeHtml(u.last_name)}</strong>
<span style="font-size:0.75rem; color:var(--text-muted); margin-left:var(--space-xs); font-weight:normal;">(Login: ${App.escapeHtml(u.login)} | Azienda: ${App.escapeHtml(u.customer_id || '—')})</span>
</div>
`).join('');
customerSuggestionsDiv.style.display = 'block';
// Bind click
customerSuggestionsDiv.querySelectorAll('.autocomplete-suggestion-item').forEach(item => {
if (item.dataset.login) {
item.addEventListener('click', () => {
customerSearchInput.value = item.dataset.name;
customerUserIdInput.value = item.dataset.login;
customerIdInput.value = item.dataset.customerId || '';
customerSuggestionsDiv.style.display = 'none';
customerUserIdInput.dispatchEvent(new Event('change'));
customerIdInput.dispatchEvent(new Event('change'));
});
}
});
} catch (err) {
console.error(err);
}
}, 300);
});
}
// Close suggestions on click outside
document.addEventListener('click', (e) => {
if (customerSearchInput && e.target !== customerSearchInput && e.target !== customerSuggestionsDiv) {
customerSuggestionsDiv.style.display = 'none';
}
});
// Reset quick-edit
resetBtn.addEventListener('click', () => {
selects.forEach(sel => {
sel.value = this.originalValues[sel.dataset.field] || '';
sel.classList.remove('changed');
fields.forEach(el => {
el.value = this.originalValues[el.dataset.field] || '';
el.classList.remove('changed');
});
if (customerSearchInput) {
const first = this.originalValues['customer_first'] || '';
const last = this.originalValues['customer_last'] || '';
customerSearchInput.value = first ? `${first} ${last}` : (this.originalValues['customer_user_id'] || '');
}
saveBtn.disabled = true;
});
// Save quick-edit
saveBtn.addEventListener('click', async () => {
const updates = {};
selects.forEach(sel => {
const field = sel.dataset.field;
const val = sel.value ? parseInt(sel.value) : null;
if (val !== null && val !== this.originalValues[field]) {
fields.forEach(el => {
const field = el.dataset.field;
let val;
if (field === 'customer_id' || field === 'customer_user_id') {
val = el.value || null;
} else {
val = el.value ? parseInt(el.value) : null;
}
const origVal = this.originalValues[field] || null;
if (val !== origVal) {
updates[field] = val;
}
});