import { t, i18n } from '../../i18n.js'; import { router } from '../../router.js'; import '../search-box.js'; import '../listing-card.js'; class PageSearch extends HTMLElement { constructor() { super(); this.results = []; this.loading = false; } connectedCallback() { this.parseUrlParams(); this.render(); this.afterRender(); this.unsubscribe = i18n.subscribe(() => { this.render(); this.afterRender(); }); if (this.hasFilters()) { this.performSearch(); } } disconnectedCallback() { if (this.unsubscribe) this.unsubscribe(); } parseUrlParams() { const params = new URLSearchParams(window.location.hash.split('?')[1] || ''); this.query = params.get('q') || ''; this.category = params.get('category') || ''; this.subcategory = params.get('sub') || ''; this.country = params.get('country') || 'ch'; this.useCurrentLocation = params.get('location') === 'current'; this.radius = parseInt(params.get('radius')) || 50; this.lat = params.get('lat') ? parseFloat(params.get('lat')) : null; this.lng = params.get('lng') ? parseFloat(params.get('lng')) : null; } hasFilters() { return this.query || this.category || this.subcategory; } afterRender() { const searchBox = this.querySelector('search-box'); if (searchBox) { searchBox.setFilters({ query: this.query, category: this.category, subcategory: this.subcategory, country: this.country, useCurrentLocation: this.useCurrentLocation, radius: this.radius }); searchBox.addEventListener('search', (e) => { this.handleSearch(e.detail); }); } } handleSearch(filters) { this.query = filters.query; this.category = filters.category; this.subcategory = filters.subcategory; this.country = filters.country; this.useCurrentLocation = filters.useCurrentLocation; this.radius = filters.radius; this.lat = filters.lat; this.lng = filters.lng; this.performSearch(); } render() { this.innerHTML = /* html */ `
${this.renderResults()}
`; } async performSearch() { this.loading = true; this.updateResults(); await new Promise(resolve => setTimeout(resolve, 500)); this.results = this.getMockResults(); this.loading = false; this.updateResults(); } getMockResults() { return [ { id: 1, title: 'iPhone 13 Pro', price: 699, location: 'Berlin' }, { id: 2, title: 'Vintage Sofa', price: 250, location: 'München' }, { id: 3, title: 'Mountain Bike', price: 450, location: 'Hamburg' }, { id: 4, title: 'Gaming PC', price: 1200, location: 'Köln' }, { id: 5, title: 'Schreibtisch', price: 80, location: 'Zürich' }, { id: 6, title: 'Winterjacke', price: 45, location: 'Wien' }, ]; } updateResults() { const resultsContainer = this.querySelector('#results'); if (resultsContainer) { resultsContainer.innerHTML = this.renderResults(); } } renderResults() { if (this.loading) { return /* html */ `

${t('search.loading')}

`; } if (!this.hasFilters() && this.results.length === 0) { return /* html */ `
🔍

${t('search.enterQuery')}

`; } if (this.results.length === 0) { return /* html */ `
😕

${t('search.noResults')}

`; } return /* html */ `

${t('search.resultsCount', { count: this.results.length })}

${this.results.map(item => /* html */ ` `).join('')}
`; } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } } customElements.define('page-search', PageSearch); const style = document.createElement('style'); style.textContent = /* css */ ` page-search .search-page { padding: var(--space-lg) 0; } page-search .search-header { margin-bottom: var(--space-xl); } page-search .results-count { color: var(--color-text-muted); margin-bottom: var(--space-md); } page-search .listings-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-md); } @media (min-width: 768px) { page-search .listings-grid { grid-template-columns: repeat(4, 1fr); } } page-search .loading { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-2xl); color: var(--color-text-muted); } page-search .spinner { width: 40px; height: 40px; border: 3px solid var(--color-border); border-top-color: var(--color-primary); border-radius: 50%; animation: spin 1s linear infinite; margin-bottom: var(--space-md); } @keyframes spin { to { transform: rotate(360deg); } } page-search .empty-state { text-align: center; padding: var(--space-2xl); color: var(--color-text-muted); } page-search .empty-state-icon { font-size: 3rem; margin-bottom: var(--space-md); } `; document.head.appendChild(style);