implement directus listings
This commit is contained in:
@@ -1,11 +1,20 @@
|
||||
import { t, i18n } from '../../i18n.js'
|
||||
import { mockListings } from '../../data/mock-listings.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
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render()
|
||||
this.loadListings()
|
||||
this.unsubscribe = i18n.subscribe(() => this.render())
|
||||
}
|
||||
|
||||
@@ -13,6 +22,24 @@ class PageHome extends HTMLElement {
|
||||
if (this.unsubscribe) this.unsubscribe()
|
||||
}
|
||||
|
||||
async loadListings() {
|
||||
try {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
this.render()
|
||||
|
||||
const response = await listingsService.getRecentListings(12)
|
||||
this.listings = response.items || []
|
||||
this.loading = false
|
||||
this.render()
|
||||
} catch (err) {
|
||||
console.error('Failed to load listings:', err)
|
||||
this.error = err.message
|
||||
this.loading = false
|
||||
this.render()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.innerHTML = /* html */`
|
||||
<section class="search-section">
|
||||
@@ -29,14 +56,34 @@ class PageHome extends HTMLElement {
|
||||
}
|
||||
|
||||
renderListings() {
|
||||
return mockListings.map(listing => /* html */`
|
||||
<listing-card
|
||||
listing-id="${listing.id}"
|
||||
title="${listing.title}"
|
||||
price="${listing.price}"
|
||||
location="${listing.location}"
|
||||
></listing-card>
|
||||
`).join('')
|
||||
if (this.loading) {
|
||||
return /* html */`<p class="loading-text">${t('common.loading') || 'Laden...'}</p>`
|
||||
}
|
||||
|
||||
if (this.error) {
|
||||
return /* html */`<p class="error-text">${t('common.error') || 'Fehler beim Laden'}</p>`
|
||||
}
|
||||
|
||||
if (this.listings.length === 0) {
|
||||
return /* html */`<p class="empty-text">${t('home.noListings') || 'Keine Anzeigen gefunden'}</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 || listing.location || ''
|
||||
|
||||
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('')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { t, i18n } from '../../i18n.js'
|
||||
import { router } from '../../router.js'
|
||||
import { searchListings } from '../../data/mock-listings.js'
|
||||
import { listingsService } from '../../services/listings.js'
|
||||
import { directus } from '../../services/directus.js'
|
||||
import '../search-box.js'
|
||||
import '../listing-card.js'
|
||||
|
||||
@@ -9,6 +10,7 @@ class PageSearch extends HTMLElement {
|
||||
super()
|
||||
this.results = []
|
||||
this.loading = false
|
||||
this.error = null
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
@@ -92,17 +94,26 @@ class PageSearch extends HTMLElement {
|
||||
|
||||
async performSearch() {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
this.updateResults()
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
this.results = this.getMockResults()
|
||||
this.loading = false
|
||||
this.updateResults()
|
||||
}
|
||||
|
||||
getMockResults() {
|
||||
return searchListings(this.query, this.category, this.subcategory)
|
||||
try {
|
||||
const filters = {
|
||||
search: this.query || undefined,
|
||||
category: this.category || undefined,
|
||||
limit: 50
|
||||
}
|
||||
|
||||
const response = await listingsService.getListingsWithFilters(filters)
|
||||
this.results = response.items || []
|
||||
this.loading = false
|
||||
this.updateResults()
|
||||
} catch (err) {
|
||||
console.error('Search failed:', err)
|
||||
this.error = err.message
|
||||
this.loading = false
|
||||
this.updateResults()
|
||||
}
|
||||
}
|
||||
|
||||
updateResults() {
|
||||
@@ -122,6 +133,15 @@ class PageSearch extends HTMLElement {
|
||||
`
|
||||
}
|
||||
|
||||
if (this.error) {
|
||||
return /* html */`
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">⚠️</div>
|
||||
<p>${t('common.error')}</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
if (!this.hasFilters() && this.results.length === 0) {
|
||||
return /* html */`
|
||||
<div class="empty-state">
|
||||
@@ -143,14 +163,22 @@ class PageSearch extends HTMLElement {
|
||||
return /* html */`
|
||||
<p class="results-count">${t('search.resultsCount', { count: this.results.length })}</p>
|
||||
<div class="listings-grid">
|
||||
${this.results.map(item => /* html */`
|
||||
<listing-card
|
||||
listing-id="${item.id}"
|
||||
title="${this.escapeHtml(item.title)}"
|
||||
price="${item.price}"
|
||||
location="${this.escapeHtml(item.location)}"
|
||||
></listing-card>
|
||||
`).join('')}
|
||||
${this.results.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 || listing.location || ''
|
||||
|
||||
return /* html */`
|
||||
<listing-card
|
||||
listing-id="${listing.id}"
|
||||
title="${this.escapeHtml(listing.title || '')}"
|
||||
price="${listing.price || ''}"
|
||||
currency="${listing.currency || 'EUR'}"
|
||||
location="${this.escapeHtml(locationName)}"
|
||||
image="${imageUrl}"
|
||||
></listing-card>
|
||||
`
|
||||
}).join('')}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { directus } from './directus.js'
|
||||
import { currencyService } from './currency.js'
|
||||
import currency from './currency.js'
|
||||
|
||||
class ListingsService {
|
||||
constructor() {
|
||||
@@ -34,12 +34,9 @@ class ListingsService {
|
||||
const listing = await directus.getListing(id)
|
||||
if (!listing) return null
|
||||
|
||||
if (listing.price && listing.price_mode === 'xmr') {
|
||||
const fiatPrice = await currencyService.xmrToFiat(listing.price, targetCurrency)
|
||||
listing.price_converted = fiatPrice
|
||||
listing.price_converted_currency = targetCurrency
|
||||
} else if (listing.price && listing.currency === 'XMR') {
|
||||
const fiatPrice = await currencyService.xmrToFiat(listing.price, targetCurrency)
|
||||
if (listing.price && (listing.price_mode === 'xmr' || listing.currency === 'XMR')) {
|
||||
const rates = await currency.getXmrRates()
|
||||
const fiatPrice = currency.convertFromXmr(listing.price, targetCurrency, rates)
|
||||
listing.price_converted = fiatPrice
|
||||
listing.price_converted_currency = targetCurrency
|
||||
}
|
||||
@@ -51,7 +48,7 @@ class ListingsService {
|
||||
const directusFilter = { status: { _eq: 'published' } }
|
||||
|
||||
if (filters.category) {
|
||||
directusFilter.category = { _eq: filters.category }
|
||||
directusFilter.category = { slug: { _eq: filters.category } }
|
||||
}
|
||||
|
||||
if (filters.location) {
|
||||
|
||||
@@ -23,7 +23,12 @@
|
||||
"placeholderTitle": "Beispielanzeige",
|
||||
"placeholderLocation": "Standort",
|
||||
"addFavorite": "Zu Favoriten hinzufügen",
|
||||
"removeFavorite": "Aus Favoriten entfernen"
|
||||
"removeFavorite": "Aus Favoriten entfernen",
|
||||
"noListings": "Keine Anzeigen gefunden"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Laden...",
|
||||
"error": "Fehler beim Laden"
|
||||
},
|
||||
"categories": {
|
||||
"electronics": "Elektronik",
|
||||
@@ -139,6 +144,7 @@
|
||||
"shippingAvailable": "Versand möglich",
|
||||
"location": "Standort",
|
||||
"locationPlaceholder": "Stadt, PLZ oder Adresse",
|
||||
"locationHint": "Wähle den Standort für deine Anzeige",
|
||||
"description": "Beschreibung",
|
||||
"descriptionPlaceholder": "Beschreibe deinen Artikel ausführlich...",
|
||||
"images": "Bilder",
|
||||
|
||||
@@ -23,7 +23,12 @@
|
||||
"placeholderTitle": "Sample Listing",
|
||||
"placeholderLocation": "Location",
|
||||
"addFavorite": "Add to favorites",
|
||||
"removeFavorite": "Remove from favorites"
|
||||
"removeFavorite": "Remove from favorites",
|
||||
"noListings": "No listings found"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Loading...",
|
||||
"error": "Error loading"
|
||||
},
|
||||
"categories": {
|
||||
"electronics": "Electronics",
|
||||
@@ -139,6 +144,7 @@
|
||||
"shippingAvailable": "Shipping available",
|
||||
"location": "Location",
|
||||
"locationPlaceholder": "City, ZIP or address",
|
||||
"locationHint": "Choose the location for your listing",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Describe your item in detail...",
|
||||
"images": "Images",
|
||||
|
||||
@@ -23,7 +23,12 @@
|
||||
"placeholderTitle": "Exemple d'annonce",
|
||||
"placeholderLocation": "Emplacement",
|
||||
"addFavorite": "Ajouter aux favoris",
|
||||
"removeFavorite": "Retirer des favoris"
|
||||
"removeFavorite": "Retirer des favoris",
|
||||
"noListings": "Aucune annonce trouvée"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Chargement...",
|
||||
"error": "Erreur de chargement"
|
||||
},
|
||||
"categories": {
|
||||
"electronics": "Électronique",
|
||||
@@ -139,6 +144,7 @@
|
||||
"shippingAvailable": "Livraison disponible",
|
||||
"location": "Emplacement",
|
||||
"locationPlaceholder": "Ville, code postal ou adresse",
|
||||
"locationHint": "Choisissez l'emplacement de votre annonce",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Décrivez votre article en détail...",
|
||||
"images": "Images",
|
||||
|
||||
Reference in New Issue
Block a user