improve listing
This commit is contained in:
@@ -394,6 +394,14 @@ app-shell main {
|
||||
margin-bottom: var(--space-md);
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.empty-state .btn {
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
/* Dropdown */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
|
||||
@@ -53,9 +53,12 @@ class PageListing extends HTMLElement {
|
||||
return
|
||||
}
|
||||
|
||||
const images = this.listing.images || []
|
||||
const images = (this.listing.images || []).slice(0, 5)
|
||||
const hasImages = images.length > 0
|
||||
const firstImage = hasImages ? this.getImageUrl(images[0]) : null
|
||||
const firstImage = hasImages ? this.getImageUrl(images[0], 800) : null
|
||||
this.currentImageIndex = 0
|
||||
this.allImages = images
|
||||
|
||||
const placeholderSvg = /* html */`
|
||||
<svg class="placeholder-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
@@ -65,7 +68,6 @@ class PageListing extends HTMLElement {
|
||||
`
|
||||
|
||||
const categoryName = this.listing.category?.name || this.listing.category?.slug || ''
|
||||
const locationName = this.listing.location?.name || ''
|
||||
const price = this.formatPrice(this.listing.price, this.listing.currency)
|
||||
const createdDate = this.listing.date_created
|
||||
? new Date(this.listing.date_created).toLocaleDateString()
|
||||
@@ -74,16 +76,16 @@ class PageListing extends HTMLElement {
|
||||
this.innerHTML = /* html */`
|
||||
<article class="listing-detail">
|
||||
<div class="listing-gallery">
|
||||
<div class="listing-image-main">
|
||||
<div class="listing-image-main" id="main-image">
|
||||
${firstImage
|
||||
? `<img src="${firstImage}" alt="${this.escapeHtml(this.listing.title)}">`
|
||||
? `<img src="${firstImage}" alt="${this.escapeHtml(this.listing.title)}" id="main-img">`
|
||||
: placeholderSvg}
|
||||
</div>
|
||||
${images.length > 1 ? `
|
||||
<div class="listing-thumbnails">
|
||||
${images.map((img, i) => `
|
||||
<button class="thumbnail ${i === 0 ? 'active' : ''}" data-index="${i}">
|
||||
<img src="${this.getImageUrl(img, 100)}" alt="">
|
||||
<img src="${this.getImageUrl(img, 150)}" alt="">
|
||||
</button>
|
||||
`).join('')}
|
||||
</div>
|
||||
@@ -95,7 +97,6 @@ class PageListing extends HTMLElement {
|
||||
${categoryName ? `<span class="badge badge-primary">${this.escapeHtml(categoryName)}</span>` : ''}
|
||||
<h1>${this.escapeHtml(this.listing.title)}</h1>
|
||||
<p class="listing-price">${price}</p>
|
||||
${locationName ? `<p class="listing-location">📍 ${this.escapeHtml(locationName)}</p>` : ''}
|
||||
${this.listing.condition ? `<p class="listing-condition">${this.getConditionLabel(this.listing.condition)}</p>` : ''}
|
||||
</header>
|
||||
|
||||
@@ -220,6 +221,22 @@ class PageListing extends HTMLElement {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Thumbnail gallery
|
||||
const thumbnails = this.querySelectorAll('.thumbnail')
|
||||
const mainImg = this.querySelector('#main-img')
|
||||
|
||||
thumbnails.forEach(thumb => {
|
||||
thumb.addEventListener('click', () => {
|
||||
const index = parseInt(thumb.dataset.index)
|
||||
if (mainImg && this.allImages[index]) {
|
||||
mainImg.src = this.getImageUrl(this.allImages[index], 800)
|
||||
thumbnails.forEach(t => t.classList.remove('active'))
|
||||
thumb.classList.add('active')
|
||||
this.currentImageIndex = index
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getImageUrl(image, size = null) {
|
||||
@@ -297,6 +314,14 @@ style.textContent = /* css */`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
page-listing .listing-image-main img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
background: var(--color-bg-tertiary);
|
||||
}
|
||||
|
||||
page-listing .listing-image-main .placeholder-icon {
|
||||
@@ -305,6 +330,47 @@ style.textContent = /* css */`
|
||||
color: var(--color-border);
|
||||
}
|
||||
|
||||
page-listing .listing-thumbnails {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: var(--space-xs);
|
||||
padding: var(--space-xs);
|
||||
background: var(--color-bg-secondary);
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
page-listing .listing-thumbnails {
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
page-listing .thumbnail {
|
||||
aspect-ratio: 1;
|
||||
border: 2px solid transparent;
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: border-color var(--transition-fast), opacity var(--transition-fast);
|
||||
padding: 0;
|
||||
background: var(--color-bg-tertiary);
|
||||
}
|
||||
|
||||
page-listing .thumbnail:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
page-listing .thumbnail.active {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
page-listing .thumbnail img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
page-listing .listing-info header {
|
||||
margin-bottom: var(--space-xl);
|
||||
}
|
||||
|
||||
@@ -253,16 +253,19 @@ class DirectusService {
|
||||
async getListings(options = {}) {
|
||||
const params = {
|
||||
fields: options.fields || [
|
||||
'*',
|
||||
'id',
|
||||
'status',
|
||||
'title',
|
||||
'slug',
|
||||
'price',
|
||||
'currency',
|
||||
'condition',
|
||||
'date_created',
|
||||
'images.directus_files_id.id',
|
||||
'images.directus_files_id.title',
|
||||
'category.id',
|
||||
'category.name',
|
||||
'category.slug',
|
||||
'category.icon',
|
||||
'location.id',
|
||||
'location.name',
|
||||
'location.region'
|
||||
'category.icon'
|
||||
],
|
||||
filter: options.filter || { status: { _eq: 'published' } },
|
||||
sort: options.sort || ['-date_created'],
|
||||
@@ -284,11 +287,26 @@ class DirectusService {
|
||||
async getListing(id) {
|
||||
const response = await this.get(`/items/listings/${id}`, {
|
||||
fields: [
|
||||
'*',
|
||||
'images.directus_files_id.*',
|
||||
'category.*',
|
||||
'category.translations.*',
|
||||
'location.*'
|
||||
'id',
|
||||
'status',
|
||||
'title',
|
||||
'slug',
|
||||
'description',
|
||||
'price',
|
||||
'currency',
|
||||
'price_mode',
|
||||
'price_type',
|
||||
'condition',
|
||||
'shipping',
|
||||
'shipping_cost',
|
||||
'views',
|
||||
'expires_at',
|
||||
'monero_address',
|
||||
'date_created',
|
||||
'images.directus_files_id.id',
|
||||
'category.id',
|
||||
'category.name',
|
||||
'category.slug'
|
||||
]
|
||||
})
|
||||
return response.data
|
||||
|
||||
Reference in New Issue
Block a user