210 lines
6.3 KiB
JavaScript
210 lines
6.3 KiB
JavaScript
import { t, i18n } from '../../i18n.js';
|
|
|
|
class PageListing extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.listing = null;
|
|
this.loading = true;
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.listingId = this.dataset.id;
|
|
this.render();
|
|
this.loadListing();
|
|
this.unsubscribe = i18n.subscribe(() => this.render());
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
if (this.unsubscribe) this.unsubscribe();
|
|
}
|
|
|
|
async loadListing() {
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
this.listing = {
|
|
id: this.listingId,
|
|
title: 'iPhone 13 Pro - Sehr guter Zustand',
|
|
description: 'Verkaufe mein iPhone 13 Pro in sehr gutem Zustand. Das Gerät hat keine Kratzer und funktioniert einwandfrei. Originalverpackung und Ladekabel sind dabei.',
|
|
price: 699,
|
|
location: 'Berlin, Mitte',
|
|
category: 'electronics',
|
|
createdAt: new Date().toISOString(),
|
|
seller: {
|
|
name: 'Max M.',
|
|
memberSince: '2023'
|
|
},
|
|
images: []
|
|
};
|
|
|
|
this.loading = false;
|
|
this.render();
|
|
}
|
|
|
|
render() {
|
|
if (this.loading) {
|
|
this.innerHTML = /* html */`
|
|
<div class="loading">
|
|
<div class="spinner"></div>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
if (!this.listing) {
|
|
this.innerHTML = /* html */`
|
|
<div class="empty-state">
|
|
<div class="empty-state-icon">😕</div>
|
|
<p data-i18n="listing.notFound">${t('listing.notFound')}</p>
|
|
<a href="#/" class="btn btn-primary">${t('listing.backHome')}</a>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
this.innerHTML = /* html */`
|
|
<article class="listing-detail">
|
|
<div class="listing-gallery">
|
|
<div class="listing-image-main"></div>
|
|
</div>
|
|
|
|
<div class="listing-info">
|
|
<header>
|
|
<span class="badge badge-primary">${t(`categories.${this.listing.category}`)}</span>
|
|
<h1>${this.escapeHtml(this.listing.title)}</h1>
|
|
<p class="listing-price">€ ${this.listing.price}</p>
|
|
<p class="listing-location">📍 ${this.escapeHtml(this.listing.location)}</p>
|
|
</header>
|
|
|
|
<section class="listing-description">
|
|
<h2 data-i18n="listing.description">${t('listing.description')}</h2>
|
|
<p>${this.escapeHtml(this.listing.description)}</p>
|
|
</section>
|
|
|
|
<section class="listing-seller">
|
|
<h2 data-i18n="listing.seller">${t('listing.seller')}</h2>
|
|
<div class="seller-card">
|
|
<div class="seller-avatar">${this.listing.seller.name.charAt(0)}</div>
|
|
<div class="seller-info">
|
|
<strong>${this.escapeHtml(this.listing.seller.name)}</strong>
|
|
<span>${t('listing.memberSince')} ${this.listing.seller.memberSince}</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="listing-actions">
|
|
<button class="btn btn-primary btn-lg">
|
|
${t('listing.contactSeller')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
`;
|
|
}
|
|
|
|
escapeHtml(text) {
|
|
const div = document.createElement('div');
|
|
div.textContent = text;
|
|
return div.innerHTML;
|
|
}
|
|
}
|
|
|
|
customElements.define('page-listing', PageListing);
|
|
|
|
const style = document.createElement('style');
|
|
style.textContent = /* css */`
|
|
page-listing .listing-detail {
|
|
display: grid;
|
|
grid-template-columns: 1fr 400px;
|
|
gap: var(--space-xl);
|
|
padding: var(--space-lg) 0;
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
page-listing .listing-detail {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
page-listing .listing-gallery {
|
|
background: var(--color-bg-secondary);
|
|
border-radius: var(--radius-lg);
|
|
overflow: hidden;
|
|
}
|
|
|
|
page-listing .listing-image-main {
|
|
aspect-ratio: 4 / 3;
|
|
background: var(--color-bg-tertiary);
|
|
}
|
|
|
|
page-listing .listing-info header {
|
|
margin-bottom: var(--space-xl);
|
|
}
|
|
|
|
page-listing .listing-info h1 {
|
|
margin: var(--space-sm) 0;
|
|
}
|
|
|
|
page-listing .listing-price {
|
|
font-size: var(--font-size-2xl);
|
|
font-weight: var(--font-weight-bold);
|
|
color: var(--color-primary);
|
|
}
|
|
|
|
page-listing .listing-location {
|
|
color: var(--color-text-secondary);
|
|
margin-top: var(--space-sm);
|
|
}
|
|
|
|
page-listing .listing-description,
|
|
page-listing .listing-seller {
|
|
margin-bottom: var(--space-xl);
|
|
}
|
|
|
|
page-listing .listing-description h2,
|
|
page-listing .listing-seller h2 {
|
|
font-size: var(--font-size-lg);
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
page-listing .seller-card {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-md);
|
|
padding: var(--space-md);
|
|
background: var(--color-bg-secondary);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
|
|
page-listing .seller-avatar {
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: 50%;
|
|
background: var(--color-primary);
|
|
color: white;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: var(--font-weight-bold);
|
|
font-size: var(--font-size-lg);
|
|
}
|
|
|
|
page-listing .seller-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
page-listing .seller-info span {
|
|
font-size: var(--font-size-sm);
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
page-listing .listing-actions {
|
|
margin-top: var(--space-xl);
|
|
}
|
|
|
|
page-listing .listing-actions .btn {
|
|
width: 100%;
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|