Find locations you've been to by searching for places, addresses, or business names.
`;
// Add sidepanel to body
document.body.appendChild(sidepanel);
// Store references
this.sidepanel = sidepanel;
this.searchInput = document.getElementById('location-search-input');
this.searchButton = document.getElementById('location-search-submit');
this.clearButton = document.getElementById('location-search-clear');
this.closeButton = document.getElementById('location-search-close');
this.suggestionsContainer = document.getElementById('location-search-suggestions');
this.suggestionsPanel = document.getElementById('location-search-suggestions-panel');
this.resultsContainer = document.getElementById('location-search-results');
this.resultsPanel = document.getElementById('location-search-results-panel');
this.defaultPanel = document.getElementById('location-search-default');
}
bindSearchEvents() {
// Toggle sidepanel visibility
this.toggleButton.addEventListener('click', () => {
this.showSidepanel();
});
// Close sidepanel
this.closeButton.addEventListener('click', () => {
this.hideSidepanel();
});
// Search on button click
this.searchButton.addEventListener('click', () => {
this.performSearch();
});
// Search on Enter key
this.searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
if (this.suggestionsVisible && this.currentSuggestionIndex >= 0) {
this.selectSuggestion(this.currentSuggestionIndex);
} else {
this.performSearch();
}
}
});
// Clear search
this.clearButton.addEventListener('click', () => {
this.clearSearch();
});
// Show clear button when input has content and handle real-time suggestions
this.searchInput.addEventListener('input', (e) => {
const query = e.target.value.trim();
if (query.length > 0) {
this.clearButton.classList.remove('hidden');
this.debouncedSuggestionSearch(query);
} else {
this.clearButton.classList.add('hidden');
this.hideSuggestions();
this.showDefaultState();
}
});
// Handle keyboard navigation for suggestions
this.searchInput.addEventListener('keydown', (e) => {
if (this.suggestionsVisible) {
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
this.navigateSuggestions(1);
break;
case 'ArrowUp':
e.preventDefault();
this.navigateSuggestions(-1);
break;
case 'Escape':
this.hideSuggestions();
this.showDefaultState();
break;
}
}
});
// Close sidepanel on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.searchVisible) {
this.hideSidepanel();
}
});
// Close sidepanel when clicking outside
document.addEventListener('click', (e) => {
if (this.searchVisible &&
!e.target.closest('.location-search-sidepanel') &&
!e.target.closest('#location-search-toggle')) {
this.hideSidepanel();
}
});
}
async performSearch() {
const query = this.searchInput.value.trim();
if (!query) return;
this.currentSearchQuery = query;
this.showLoading();
try {
const response = await fetch(`/api/v1/locations?q=${encodeURIComponent(query)}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Search failed: ${response.status} ${response.statusText}`);
}
const data = await response.json();
this.displaySearchResults(data);
} catch (error) {
console.error('Location search error:', error);
this.showError('Failed to search locations. Please try again.');
}
}
showLoading() {
// Hide other panels and show results with loading
this.defaultPanel.classList.add('hidden');
this.suggestionsPanel.classList.add('hidden');
this.resultsPanel.classList.remove('hidden');
this.resultsContainer.innerHTML = `
Searching for "${this.currentSearchQuery}"...
`;
}
showError(message) {
// Hide other panels and show results with error
this.defaultPanel.classList.add('hidden');
this.suggestionsPanel.classList.add('hidden');
this.resultsPanel.classList.remove('hidden');
this.resultsContainer.innerHTML = `
⚠️
Search Failed
${message}
`;
}
displaySearchResults(data) {
// Hide other panels and show results
this.defaultPanel.classList.add('hidden');
this.suggestionsPanel.classList.add('hidden');
this.resultsPanel.classList.remove('hidden');
if (!data.locations || data.locations.length === 0) {
this.resultsContainer.innerHTML = `