Files
old-zsterminator/app/javascript/controllers/customer_search_controller.js

156 lines
4.5 KiB
JavaScript

import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["select", "phoneField", "birthYearField", "firstNameField", "surnameField", "newCustomerFields"]
static values = {
existingId: String,
existingLabel: String
}
connect() {
let initialOptions = [];
let initialValue = null;
if (this.hasExistingIdValue && this.hasExistingLabelValue && this.existingIdValue.length > 0) {
initialOptions = [{ id: this.existingIdValue, label: this.existingLabelValue }];
initialValue = this.existingIdValue;
}
this.selectInstance = new TomSelect(this.selectTarget, {
valueField: 'id',
labelField: 'label',
searchField: ['label'],
maxItems: 1,
create: true,
createOnBlur: true,
placeholder: 'Type to search customers...',
create: function(input) {
return {
id: `${input}__new`,
label: `${input} (New Customer)`
};
},
options: initialOptions,
items: initialValue ? [initialValue] : [],
load: async (query, callback) => {
if (!query.length && !initialValue) return callback();
try {
const response = await fetch(`/customers/search?q=${encodeURIComponent(query)}`, {
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
});
const data = await response.json();
const existingOptionId = this.hasExistingIdValue ? this.existingIdValue : null;
const filteredData = data.filter(item => item.id !== existingOptionId);
callback(filteredData);
} catch (error) {
console.error('Error loading customers:', error);
callback();
}
},
shouldLoad: function(query) {
return query.length >= 2;
},
render: {
no_results: (data, escape) => {
return '<div class="no-results">No customers found. Fill in the details below.</div>';
},
option: function(item) {
const colorStyle = item.color_hex ? `background-color: ${item.color_hex}20; border-left: 4px solid ${item.color_hex};` : '';
return `<div style="${colorStyle} padding: 8px;">${item.label}</div>`;
}
},
onLoad: (data) => {
if (!this.selectInstance.getValue() && (!data || data.length === 0)) {
this.showNewCustomerFields();
}
},
onChange: (value) => {
if (value === null || value === '') {
this.showNewCustomerFields();
} else if (!value.endsWith('__new')) {
this.newCustomerFieldsTarget.classList.add('hidden');
}
},
onItemAdd: (value) => {
this.customerSelected(value);
},
onDropdownClose: (dropdown) => {
if (!this.selectInstance.getValue()) {
this.showNewCustomerFields();
}
}
});
if (initialValue) {
this.newCustomerFieldsTarget.classList.add('hidden');
this.customerSelected(initialValue);
} else {
// Show new customer fields if no existing customer
this.showNewCustomerFields();
}
}
customerSelected(value) {
if (value.endsWith('__new')) {
const firstName = value.replace('__new', '');
this.firstNameFieldTarget.value = firstName;
this.showNewCustomerFields();
return;
}
const [firstName, surname, phone] = value.split('_');
if (firstName && surname && phone) {
const customerData = this.selectInstance.options[value];
this.phoneFieldTarget.value = phone;
this.firstNameFieldTarget.value = firstName;
this.surnameFieldTarget.value = surname;
if (customerData && customerData.birthyear) {
this.birthYearFieldTarget.value = customerData.birthyear;
} else {
this.birthYearFieldTarget.value = '';
}
this.newCustomerFieldsTarget.classList.add('hidden');
} else {
console.warn("Selected customer value format unexpected:", value);
this.clearFields();
this.showNewCustomerFields();
}
}
showNewCustomerFields() {
this.newCustomerFieldsTarget.classList.remove('hidden');
}
clearFields() {
this.phoneFieldTarget.value = '';
this.firstNameFieldTarget.value = '';
this.surnameFieldTarget.value = '';
this.birthYearFieldTarget.value = '';
}
disconnect() {
if (this.selectInstance) {
this.selectInstance.destroy();
}
}
}