170 lines
4.8 KiB
JavaScript
170 lines
4.8 KiB
JavaScript
import { t, i18n } from '../../i18n.js'
|
|
import { directus } from '../../services/directus.js'
|
|
import { auth } from '../../services/auth.js'
|
|
import { favoritesService } from '../../services/favorites.js'
|
|
import { escapeHTML } from '../../utils/helpers.js'
|
|
import '../listing-card.js'
|
|
import '../skeleton-card.js'
|
|
|
|
class PageFavorites extends HTMLElement {
|
|
constructor() {
|
|
super()
|
|
this.listings = []
|
|
this.loading = true
|
|
this.error = null
|
|
}
|
|
|
|
connectedCallback() {
|
|
this._unsubs = []
|
|
this.render()
|
|
this.loadFavorites()
|
|
this._unsubs.push(i18n.subscribe(() => this.render()))
|
|
this._unsubs.push(favoritesService.subscribe(() => this.loadFavorites()))
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
this._unsubs.forEach(fn => fn())
|
|
this._unsubs = []
|
|
}
|
|
|
|
async loadFavorites() {
|
|
const ids = favoritesService.getAll()
|
|
|
|
if (ids.length === 0) {
|
|
this.loading = false
|
|
this.listings = []
|
|
this.updateContent()
|
|
return
|
|
}
|
|
|
|
try {
|
|
const response = await directus.getListings({
|
|
filter: {
|
|
id: { _in: ids },
|
|
status: { _eq: 'published' }
|
|
},
|
|
limit: 50
|
|
})
|
|
this.listings = response.items || []
|
|
this.loading = false
|
|
this.updateContent()
|
|
} catch (err) {
|
|
console.error('Failed to load favorites:', err)
|
|
this.error = err.message
|
|
this.loading = false
|
|
this.updateContent()
|
|
}
|
|
}
|
|
|
|
render() {
|
|
this.innerHTML = /* html */`
|
|
<div class="favorites-page">
|
|
<header class="page-header">
|
|
<h1>${t('favorites.title')}</h1>
|
|
<p class="page-subtitle">${t('favorites.subtitle')}</p>
|
|
</header>
|
|
|
|
<div id="favorites-content" class="listings-grid">
|
|
${this.renderContent()}
|
|
</div>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
updateContent() {
|
|
const container = this.querySelector('#favorites-content')
|
|
if (container) {
|
|
container.innerHTML = this.renderContent()
|
|
}
|
|
}
|
|
|
|
renderContent() {
|
|
if (this.loading) {
|
|
return Array(4).fill(0).map(() => '<skeleton-card></skeleton-card>').join('')
|
|
}
|
|
|
|
if (this.error) {
|
|
return /* html */`
|
|
<div class="empty-state">
|
|
<div class="empty-icon">⚠️</div>
|
|
<p>${t('common.error')}</p>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
if (this.listings.length === 0) {
|
|
return /* html */`
|
|
<div class="empty-state">
|
|
<div class="empty-icon">❤️</div>
|
|
<h3>${t('favorites.empty')}</h3>
|
|
<p>${t('favorites.emptyHint')}</p>
|
|
<a href="#/" class="btn btn-primary">${t('favorites.browse')}</a>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
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, 180) : ''
|
|
const locationName = listing.location?.name || ''
|
|
|
|
return /* html */`
|
|
<listing-card
|
|
listing-id="${listing.id}"
|
|
title="${escapeHTML(listing.title || '')}"
|
|
price="${listing.price || ''}"
|
|
currency="${listing.currency || 'EUR'}"
|
|
location="${escapeHTML(locationName)}"
|
|
image="${imageUrl}"
|
|
owner-id="${listing.user_created || ''}"
|
|
></listing-card>
|
|
`
|
|
}).join('')
|
|
}
|
|
|
|
}
|
|
|
|
customElements.define('page-favorites', PageFavorites)
|
|
|
|
const style = document.createElement('style')
|
|
style.textContent = /* css */`
|
|
page-favorites .favorites-page {
|
|
padding: var(--space-lg) 0;
|
|
}
|
|
|
|
page-favorites .page-header {
|
|
margin-bottom: var(--space-xl);
|
|
}
|
|
|
|
page-favorites .page-header h1 {
|
|
margin: 0 0 var(--space-xs);
|
|
}
|
|
|
|
page-favorites .page-subtitle {
|
|
color: var(--color-text-muted);
|
|
margin: 0;
|
|
}
|
|
|
|
page-favorites .empty-state {
|
|
grid-column: 1 / -1;
|
|
text-align: center;
|
|
padding: var(--space-3xl);
|
|
}
|
|
|
|
page-favorites .empty-icon {
|
|
font-size: 4rem;
|
|
margin-bottom: var(--space-md);
|
|
filter: grayscale(1);
|
|
}
|
|
|
|
page-favorites .empty-state h3 {
|
|
margin: 0 0 var(--space-sm);
|
|
}
|
|
|
|
page-favorites .empty-state p {
|
|
color: var(--color-text-muted);
|
|
margin: 0 0 var(--space-lg);
|
|
}
|
|
`
|
|
document.head.appendChild(style)
|