feat: handle expired listings via expires_at, optimize polling to query only pending IDs, filter expired from public listings

This commit is contained in:
2026-02-07 09:58:30 +01:00
parent a3d2a3327a
commit 7505ce5555
3 changed files with 44 additions and 15 deletions

View File

@@ -7,7 +7,7 @@ let cachedRates = null
class ListingCard extends HTMLElement {
static get observedAttributes() {
return ['listing-id', 'title', 'price', 'currency', 'location', 'image', 'owner-id', 'payment-status']
return ['listing-id', 'title', 'price', 'currency', 'location', 'image', 'owner-id', 'payment-status', 'expires-at']
}
constructor() {
@@ -130,8 +130,13 @@ class ListingCard extends HTMLElement {
` : ''
const paymentStatus = this.getAttribute('payment-status')
const expiresAt = this.getAttribute('expires-at')
const isExpired = expiresAt && new Date(expiresAt) < new Date()
let paymentBadge = ''
if (paymentStatus === 'processing' || paymentStatus === 'pending') {
if (isExpired) {
paymentBadge = /* html */`<span class="payment-badge payment-expired">${t('myListings.status.expired')}</span>`
} else if (paymentStatus === 'processing' || paymentStatus === 'pending') {
paymentBadge = /* html */`<span class="payment-badge payment-processing"><span class="pulse-dot"></span>${t('myListings.status.processing')}</span>`
} else if (paymentStatus === 'expired') {
paymentBadge = /* html */`<span class="payment-badge payment-expired">${t('myListings.status.expired')}</span>`

View File

@@ -63,21 +63,37 @@ class PageMyListings extends HTMLElement {
const user = await auth.getUser()
if (!user) return
const pendingIds = this.listings
.filter(l => l.payment_status === 'processing' || l.payment_status === 'pending')
.map(l => l.id)
if (pendingIds.length === 0) {
this.stopPolling()
return
}
const response = await directus.getListings({
fields: [
'id', 'status', 'title', 'slug', 'price', 'currency',
'condition', 'payment_status', 'date_created', 'user_created',
'images.directus_files_id.id',
'location.id', 'location.name'
],
fields: ['id', 'status', 'payment_status'],
filter: {
user_created: { _eq: user.id }
id: { _in: pendingIds }
},
sort: ['-date_created'],
limit: 50
limit: pendingIds.length
})
this.listings = response.items || []
this.updateContent()
const updated = response.items || []
let changed = false
for (const item of updated) {
const existing = this.listings.find(l => l.id === item.id)
if (existing && (existing.payment_status !== item.payment_status || existing.status !== item.status)) {
existing.payment_status = item.payment_status
existing.status = item.status
changed = true
}
}
if (changed) {
this.updateContent()
}
this.startPolling()
} catch (err) {
console.error('Polling failed:', err)
@@ -96,7 +112,7 @@ class PageMyListings extends HTMLElement {
const response = await directus.getListings({
fields: [
'id', 'status', 'title', 'slug', 'price', 'currency',
'condition', 'payment_status', 'date_created', 'user_created',
'condition', 'payment_status', 'expires_at', 'date_created', 'user_created',
'images.directus_files_id.id',
'location.id', 'location.name'
],
@@ -211,6 +227,7 @@ class PageMyListings extends HTMLElement {
image="${imageUrl}"
owner-id="${listing.user_created || ''}"
payment-status="${listing.payment_status || ''}"
expires-at="${listing.expires_at || ''}"
></listing-card>
</div>
`

View File

@@ -327,6 +327,7 @@ class DirectusService {
'price',
'currency',
'condition',
'expires_at',
'date_created',
'user_created',
'images.directus_files_id.id',
@@ -341,7 +342,13 @@ class DirectusService {
'location.latitude',
'location.longitude'
],
filter: options.filter || { status: { _eq: 'published' } },
filter: options.filter || {
status: { _eq: 'published' },
_or: [
{ expires_at: { _null: true } },
{ expires_at: { _gt: '$NOW' } }
]
},
sort: options.sort || ['-date_created'],
limit: options.limit || 20,
page: options.page || 1