Files
turbovault-app/app/javascript/controllers/location_autocomplete_controller.js
2026-03-28 19:24:29 -04:00

82 lines
1.8 KiB
JavaScript

import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["input", "results"]
static values = { url: String }
connect() {
this.timeout = null
console.log("Location autocomplete connected")
}
search() {
clearTimeout(this.timeout)
const query = this.inputTarget.value.trim()
if (query.length < 1) {
this.hideResults()
return
}
this.timeout = setTimeout(() => {
this.performSearch(query)
}, 200)
}
async performSearch(query) {
const url = `${this.urlValue}?q=${encodeURIComponent(query)}`
try {
const response = await fetch(url)
const locations = await response.json()
this.displayResults(locations)
} catch (error) {
console.error("Location search error:", error)
}
}
displayResults(locations) {
if (locations.length === 0) {
this.hideResults()
return
}
const html = locations.map(location => `
<div class="px-4 py-2 hover:bg-indigo-50 cursor-pointer text-sm"
data-action="click->location-autocomplete#selectLocation"
data-location="${this.escapeHtml(location)}">
${this.escapeHtml(location)}
</div>
`).join('')
this.resultsTarget.innerHTML = html
this.resultsTarget.classList.remove("hidden")
}
selectLocation(event) {
const location = event.currentTarget.dataset.location
this.inputTarget.value = location
this.hideResults()
}
hideResults() {
if (this.hasResultsTarget) {
this.resultsTarget.classList.add("hidden")
}
}
escapeHtml(text) {
const div = document.createElement('div')
div.textContent = text
return div.innerHTML
}
// Hide results when clicking outside
clickOutside(event) {
if (!this.element.contains(event.target)) {
this.hideResults()
}
}
}