feat: payment status badge in listing-card, webhook debug info, UX fixes

This commit is contained in:
2026-02-06 15:22:48 +01:00
parent d9202f9ca2
commit a532fa120f
6 changed files with 114 additions and 8 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']
return ['listing-id', 'title', 'price', 'currency', 'location', 'image', 'owner-id', 'payment-status']
}
constructor() {
@@ -129,6 +129,13 @@ class ListingCard extends HTMLElement {
</a>
` : ''
const paymentStatus = this.getAttribute('payment-status')
const paymentBadge = paymentStatus === 'processing'
? /* html */`<span class="payment-badge payment-processing"><span class="pulse-dot"></span>${t('payment.awaitingConfirmation')}</span>`
: paymentStatus === 'pending'
? /* html */`<span class="payment-badge payment-pending">${t('payment.pending')}</span>`
: ''
this.innerHTML = /* html */`
${ownerBadge}
<a href="#/listing/${escapeHTML(id)}" class="listing-link">
@@ -136,6 +143,7 @@ class ListingCard extends HTMLElement {
${image
? `<img src="${escapeHTML(image)}" alt="${escapeHTML(title)}" loading="lazy">`
: placeholderSvg}
${paymentBadge}
</div>
<div class="listing-info">
<h3 class="listing-title">${escapeHTML(title)}</h3>
@@ -220,6 +228,45 @@ style.textContent = /* css */`
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
}
listing-card .payment-badge {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: var(--space-xs) var(--space-sm);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
text-align: center;
}
listing-card .payment-processing {
background: rgba(230, 167, 0, 0.9);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
listing-card .payment-pending {
background: rgba(230, 167, 0, 0.9);
color: #fff;
}
listing-card .pulse-dot {
width: 6px;
height: 6px;
border-radius: var(--radius-full);
background: #fff;
animation: card-pulse 1.5s ease-in-out infinite;
}
@keyframes card-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
listing-card .listing-image img {

View File

@@ -744,7 +744,25 @@ class PageCreate extends HTMLElement {
})
clearPendingInvoice(listingId)
router.navigate(`/listing/${listingId}`)
this.showPaymentSuccess()
}
showPaymentSuccess() {
this.innerHTML = /* html */`
<div class="create-page">
<div class="payment-success">
<div class="success-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 6 12 12 16 14"></polyline>
</svg>
</div>
<h2>${t('payment.processing')}</h2>
<p>${t('payment.awaitingHint')}</p>
<a href="#/my-listings" class="btn btn-primary">${t('profile.myListings')}</a>
</div>
</div>
`
}
showError(message) {
@@ -993,5 +1011,28 @@ style.textContent = /* css */`
page-create .btn-link:hover {
color: var(--color-primary-hover);
}
page-create .payment-success {
text-align: center;
padding: var(--space-3xl) 0;
}
page-create .success-icon {
color: var(--color-warning, #e6a700);
margin-bottom: var(--space-lg);
}
page-create .payment-success h2 {
margin-bottom: var(--space-md);
}
page-create .payment-success p {
color: var(--color-text-secondary);
margin-bottom: var(--space-xl);
max-width: 400px;
margin-left: auto;
margin-right: auto;
line-height: 1.5;
}
`
document.head.appendChild(style)

View File

@@ -164,7 +164,7 @@ class PageListing extends HTMLElement {
? new Date(this.listing.date_created).toLocaleDateString()
: ''
this.innerHTML = /* html */`
this.innerHTML = /* html */`
<article class="listing-detail">
<!-- Two Column Layout -->
<div class="listing-layout">
@@ -1000,7 +1000,7 @@ style.textContent = /* css */`
text-align: center;
}
/* Payment Processing Badge */
/* Payment Processing Badge (sidebar) */
page-listing .payment-processing-card {
background: var(--color-bg-secondary);
border: 1px solid var(--color-warning, #e6a700);

View File

@@ -71,6 +71,16 @@ class PageMyListings extends HTMLElement {
document.querySelector('auth-modal')?.show()
}
getStatusBadge(listing) {
if (listing.status === 'archived') {
return `<span class="status-badge status-archived">${t('myListings.status.archived')}</span>`
}
if (listing.status === 'draft' && listing.payment_status !== 'processing' && listing.payment_status !== 'pending') {
return `<span class="status-badge status-draft">${t('myListings.status.draft')}</span>`
}
return ''
}
render() {
this.innerHTML = /* html */`
<div class="my-listings-page">
@@ -136,9 +146,7 @@ class PageMyListings extends HTMLElement {
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 || ''
const statusBadge = listing.status !== 'published'
? `<span class="status-badge status-${listing.status}">${t(`myListings.status.${listing.status}`)}</span>`
: ''
const statusBadge = this.getStatusBadge(listing)
return /* html */`
<div class="listing-wrapper">
@@ -151,6 +159,7 @@ class PageMyListings extends HTMLElement {
location="${escapeHTML(locationName)}"
image="${imageUrl}"
owner-id="${listing.user_created || ''}"
payment-status="${listing.payment_status || ''}"
></listing-card>
</div>
`

View File

@@ -327,6 +327,7 @@ class DirectusService {
'price',
'currency',
'condition',
'payment_status',
'date_created',
'user_created',
'images.directus_files_id.id',
@@ -379,6 +380,7 @@ class DirectusService {
'shipping',
'shipping_cost',
'views',
'payment_status',
'expires_at',
'monero_address',
'date_created',