Files
kashilo/js/components/pages/page-home.js

169 lines
4.9 KiB
JavaScript

import { t, i18n } from '../../i18n.js'
import { listingsService } from '../../services/listings.js'
import { directus } from '../../services/directus.js'
import '../listing-card.js'
import '../search-box.js'
class PageHome extends HTMLElement {
constructor() {
super()
this.listings = []
this.loading = true
this.error = null
this.currentFilters = {}
}
connectedCallback() {
this.render()
this.setupEventListeners()
this.loadListings()
this.unsubscribe = i18n.subscribe(() => {
this.render()
this.setupEventListeners()
})
}
disconnectedCallback() {
if (this.unsubscribe) this.unsubscribe()
}
setupEventListeners() {
const searchBox = this.querySelector('search-box')
// Listen for filter changes (live update)
searchBox?.addEventListener('filter-change', (e) => {
this.currentFilters = e.detail
this.loadListings()
})
// Listen for search submit (with query)
searchBox?.addEventListener('search', (e) => {
e.preventDefault()
e.stopPropagation()
this.currentFilters = e.detail
this.loadListings()
return false
})
}
async loadListings() {
try {
this.loading = true
this.error = null
this.updateListingsSection()
const filters = {
search: this.currentFilters.query || undefined,
category: this.currentFilters.category || undefined,
limit: 20
}
const response = await listingsService.getListingsWithFilters(filters)
this.listings = response.items || []
this.loading = false
this.updateListingsSection()
} catch (err) {
console.error('Failed to load listings:', err)
this.error = err.message
this.loading = false
this.updateListingsSection()
}
}
updateListingsSection() {
const listingsGrid = this.querySelector('.listings-grid')
const sectionTitle = this.querySelector('.listings-title')
if (listingsGrid) {
listingsGrid.innerHTML = this.renderListings()
}
if (sectionTitle) {
sectionTitle.textContent = this.getListingsTitle()
}
}
getListingsTitle() {
if (this.currentFilters.query || this.currentFilters.category) {
const count = this.listings.length
return t('search.resultsCount', { count }) || `${count} Ergebnisse`
}
return t('home.recentListings')
}
render() {
this.innerHTML = /* html */`
<section class="search-section">
<search-box no-navigate></search-box>
</section>
<section class="recent-listings">
<h2 class="listings-title">${this.getListingsTitle()}</h2>
<div class="listings-grid">
${this.renderListings()}
</div>
</section>
`
}
renderListings() {
if (this.loading) {
return /* html */`<p class="loading-text">${t('common.loading')}</p>`
}
if (this.error) {
return /* html */`<p class="error-text">${t('common.error')}</p>`
}
if (this.listings.length === 0) {
return /* html */`<p class="empty-text">${t('home.noListings')}</p>`
}
return this.listings.map(listing => {
const imageId = listing.images?.[0]?.directus_files_id?.id || listing.images?.[0]?.directus_files_id
const imageUrl = imageId ? directus.getThumbnailUrl(imageId, 300) : ''
const locationName = listing.location?.name || ''
return /* html */`
<listing-card
listing-id="${listing.id}"
title="${listing.title || ''}"
price="${listing.price || ''}"
currency="${listing.currency || 'EUR'}"
location="${locationName}"
image="${imageUrl}"
></listing-card>
`
}).join('')
}
}
customElements.define('page-home', PageHome)
const style = document.createElement('style')
style.textContent = /* css */`
/* Search Section */
page-home .search-section {
padding: var(--space-xl) 0;
}
/* Listings */
page-home .recent-listings {
margin-bottom: var(--space-xl);
}
page-home .listings-title {
margin-bottom: var(--space-lg);
}
page-home .loading-text,
page-home .error-text,
page-home .empty-text {
text-align: center;
padding: var(--space-xl);
color: var(--color-text-muted);
grid-column: 1 / -1;
}
`
document.head.appendChild(style)