fix: auto-set expires_at to 30 days, add expiry display on listing page, add shipping_cost field
This commit is contained in:
@@ -34,6 +34,7 @@ class PageCreate extends HTMLElement {
|
|||||||
condition: 'good',
|
condition: 'good',
|
||||||
location: '',
|
location: '',
|
||||||
shipping: false,
|
shipping: false,
|
||||||
|
shipping_cost: '',
|
||||||
moneroAddress: ''
|
moneroAddress: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,6 +104,7 @@ class PageCreate extends HTMLElement {
|
|||||||
condition: listing.condition || 'good',
|
condition: listing.condition || 'good',
|
||||||
location: listing.location?.id || listing.location || '',
|
location: listing.location?.id || listing.location || '',
|
||||||
shipping: listing.shipping || false,
|
shipping: listing.shipping || false,
|
||||||
|
shipping_cost: listing.shipping_cost?.toString() || '',
|
||||||
moneroAddress: listing.monero_address || '',
|
moneroAddress: listing.monero_address || '',
|
||||||
status: listing.status || 'published'
|
status: listing.status || 'published'
|
||||||
}
|
}
|
||||||
@@ -286,7 +288,21 @@ class PageCreate extends HTMLElement {
|
|||||||
<span>${t('create.shippingAvailable')}</span>
|
<span>${t('create.shippingAvailable')}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group shipping-cost-group" id="shipping-cost-group" style="display: ${this.formData.shipping ? 'block' : 'none'}">
|
||||||
|
<label class="label" for="shipping_cost">${t('create.shippingCost')}</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="input"
|
||||||
|
id="shipping_cost"
|
||||||
|
name="shipping_cost"
|
||||||
|
min="0"
|
||||||
|
step="0.01"
|
||||||
|
value="${this.formData.shipping_cost || ''}"
|
||||||
|
placeholder="${t('create.shippingCostPlaceholder')}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="label" for="location" data-i18n="create.location">${t('create.location')}</label>
|
<label class="label" for="location" data-i18n="create.location">${t('create.location')}</label>
|
||||||
<location-picker
|
<location-picker
|
||||||
@@ -375,10 +391,14 @@ class PageCreate extends HTMLElement {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Checkbox handler
|
// Checkbox handler with shipping cost toggle
|
||||||
const shippingCheckbox = this.querySelector('#shipping')
|
const shippingCheckbox = this.querySelector('#shipping')
|
||||||
|
const shippingCostGroup = this.querySelector('#shipping-cost-group')
|
||||||
shippingCheckbox?.addEventListener('change', (e) => {
|
shippingCheckbox?.addEventListener('change', (e) => {
|
||||||
this.formData.shipping = e.target.checked
|
this.formData.shipping = e.target.checked
|
||||||
|
if (shippingCostGroup) {
|
||||||
|
shippingCostGroup.style.display = e.target.checked ? 'block' : 'none'
|
||||||
|
}
|
||||||
this.saveDraft()
|
this.saveDraft()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -488,6 +508,7 @@ class PageCreate extends HTMLElement {
|
|||||||
category: form.querySelector('#category')?.value || '',
|
category: form.querySelector('#category')?.value || '',
|
||||||
condition: form.querySelector('#condition')?.value || 'good',
|
condition: form.querySelector('#condition')?.value || 'good',
|
||||||
shipping: form.querySelector('#shipping')?.checked || false,
|
shipping: form.querySelector('#shipping')?.checked || false,
|
||||||
|
shipping_cost: form.querySelector('#shipping_cost')?.value || '',
|
||||||
moneroAddress: form.querySelector('#moneroAddress')?.value || ''
|
moneroAddress: form.querySelector('#moneroAddress')?.value || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +561,18 @@ class PageCreate extends HTMLElement {
|
|||||||
if (formElements.category) listingData.category = formElements.category
|
if (formElements.category) listingData.category = formElements.category
|
||||||
if (formElements.condition) listingData.condition = formElements.condition
|
if (formElements.condition) listingData.condition = formElements.condition
|
||||||
listingData.shipping = formElements.shipping
|
listingData.shipping = formElements.shipping
|
||||||
|
if (formElements.shipping && formElements.shipping_cost) {
|
||||||
|
listingData.shipping_cost = parseFloat(formElements.shipping_cost)
|
||||||
|
}
|
||||||
if (formElements.moneroAddress) listingData.monero_address = formElements.moneroAddress
|
if (formElements.moneroAddress) listingData.monero_address = formElements.moneroAddress
|
||||||
|
|
||||||
|
// Calculate expires_at (only on create) - 30 days for regular users, 60 for power users
|
||||||
|
if (!this.editMode) {
|
||||||
|
const days = 30 // TODO: 60 for power users
|
||||||
|
const expiresAt = new Date()
|
||||||
|
expiresAt.setDate(expiresAt.getDate() + days)
|
||||||
|
listingData.expires_at = expiresAt.toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
// Handle location - find or create in locations collection
|
// Handle location - find or create in locations collection
|
||||||
if (this.formData.locationData) {
|
if (this.formData.locationData) {
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ class PageListing extends HTMLElement {
|
|||||||
${this.listing.condition ? `<span class="meta-item">${this.getConditionLabel(this.listing.condition)}</span>` : ''}
|
${this.listing.condition ? `<span class="meta-item">${this.getConditionLabel(this.listing.condition)}</span>` : ''}
|
||||||
${this.listing.shipping ? `<span class="meta-item">📦 ${t('listing.shippingAvailable')}</span>` : ''}
|
${this.listing.shipping ? `<span class="meta-item">📦 ${t('listing.shippingAvailable')}</span>` : ''}
|
||||||
<span class="meta-item views-item"><span class="views-icon">👁</span> ${this.formatViews(this.listing.views || 0)}</span>
|
<span class="meta-item views-item"><span class="views-icon">👁</span> ${this.formatViews(this.listing.views || 0)}</span>
|
||||||
|
${this.listing.expires_at ? `<span class="meta-item expires-item">${this.formatExpiresAt(this.listing.expires_at)}</span>` : ''}
|
||||||
<span class="meta-item meta-date">${t('listing.postedOn')} ${createdDate}</span>
|
<span class="meta-item meta-date">${t('listing.postedOn')} ${createdDate}</span>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -527,6 +528,24 @@ class PageListing extends HTMLElement {
|
|||||||
return labels[condition] || condition
|
return labels[condition] || condition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatExpiresAt(expiresAt) {
|
||||||
|
const expires = new Date(expiresAt)
|
||||||
|
const now = new Date()
|
||||||
|
const diffMs = expires - now
|
||||||
|
|
||||||
|
if (diffMs <= 0) {
|
||||||
|
return `⏱ ${t('listing.expired')}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24))
|
||||||
|
|
||||||
|
if (diffDays === 1) {
|
||||||
|
return `⏱ ${t('listing.expiresIn1Day')}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `⏱ ${t('listing.expiresInDays', { days: diffDays })}`
|
||||||
|
}
|
||||||
|
|
||||||
formatViews(count) {
|
formatViews(count) {
|
||||||
if (count === 1) {
|
if (count === 1) {
|
||||||
return `1 ${t('listing.viewSingular')}`
|
return `1 ${t('listing.viewSingular')}`
|
||||||
|
|||||||
@@ -140,7 +140,10 @@
|
|||||||
"share": "Teilen",
|
"share": "Teilen",
|
||||||
"report": "Melden",
|
"report": "Melden",
|
||||||
"moreFromSeller": "Weitere Anzeigen des Anbieters",
|
"moreFromSeller": "Weitere Anzeigen des Anbieters",
|
||||||
"edit": "Bearbeiten"
|
"edit": "Bearbeiten",
|
||||||
|
"expired": "Abgelaufen",
|
||||||
|
"expiresIn1Day": "Noch 1 Tag gültig",
|
||||||
|
"expiresInDays": "Noch {{days}} Tage gültig"
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
"title": "Nachricht senden",
|
"title": "Nachricht senden",
|
||||||
@@ -169,6 +172,8 @@
|
|||||||
"priceModeXmr": "XMR-Preis fix",
|
"priceModeXmr": "XMR-Preis fix",
|
||||||
"priceModeHint": "Fiat-fix: Der Fiat-Betrag bleibt gleich. XMR-fix: Der XMR-Betrag bleibt gleich.",
|
"priceModeHint": "Fiat-fix: Der Fiat-Betrag bleibt gleich. XMR-fix: Der XMR-Betrag bleibt gleich.",
|
||||||
"shippingAvailable": "Versand möglich",
|
"shippingAvailable": "Versand möglich",
|
||||||
|
"shippingCost": "Versandkosten",
|
||||||
|
"shippingCostPlaceholder": "z.B. 5.00",
|
||||||
"location": "Standort",
|
"location": "Standort",
|
||||||
"locationPlaceholder": "Stadt, PLZ oder Adresse",
|
"locationPlaceholder": "Stadt, PLZ oder Adresse",
|
||||||
"locationHint": "Wähle den Standort für deine Anzeige",
|
"locationHint": "Wähle den Standort für deine Anzeige",
|
||||||
|
|||||||
@@ -140,7 +140,10 @@
|
|||||||
"share": "Share",
|
"share": "Share",
|
||||||
"report": "Report",
|
"report": "Report",
|
||||||
"moreFromSeller": "More from this seller",
|
"moreFromSeller": "More from this seller",
|
||||||
"edit": "Edit"
|
"edit": "Edit",
|
||||||
|
"expired": "Expired",
|
||||||
|
"expiresIn1Day": "1 day left",
|
||||||
|
"expiresInDays": "{{days}} days left"
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
"title": "Send Message",
|
"title": "Send Message",
|
||||||
@@ -169,6 +172,8 @@
|
|||||||
"priceModeXmr": "XMR price fixed",
|
"priceModeXmr": "XMR price fixed",
|
||||||
"priceModeHint": "Fiat-fixed: The fiat amount stays the same. XMR-fixed: The XMR amount stays the same.",
|
"priceModeHint": "Fiat-fixed: The fiat amount stays the same. XMR-fixed: The XMR amount stays the same.",
|
||||||
"shippingAvailable": "Shipping available",
|
"shippingAvailable": "Shipping available",
|
||||||
|
"shippingCost": "Shipping cost",
|
||||||
|
"shippingCostPlaceholder": "e.g. 5.00",
|
||||||
"location": "Location",
|
"location": "Location",
|
||||||
"locationPlaceholder": "City, ZIP or address",
|
"locationPlaceholder": "City, ZIP or address",
|
||||||
"locationHint": "Choose the location for your listing",
|
"locationHint": "Choose the location for your listing",
|
||||||
|
|||||||
@@ -140,7 +140,10 @@
|
|||||||
"share": "Partager",
|
"share": "Partager",
|
||||||
"report": "Signaler",
|
"report": "Signaler",
|
||||||
"moreFromSeller": "Autres annonces du vendeur",
|
"moreFromSeller": "Autres annonces du vendeur",
|
||||||
"edit": "Modifier"
|
"edit": "Modifier",
|
||||||
|
"expired": "Expiré",
|
||||||
|
"expiresIn1Day": "Encore 1 jour",
|
||||||
|
"expiresInDays": "Encore {{days}} jours"
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
"title": "Envoyer un message",
|
"title": "Envoyer un message",
|
||||||
@@ -169,6 +172,8 @@
|
|||||||
"priceModeXmr": "Prix XMR fixe",
|
"priceModeXmr": "Prix XMR fixe",
|
||||||
"priceModeHint": "Fiat-fixe: Le montant fiat reste le même. XMR-fixe: Le montant XMR reste le même.",
|
"priceModeHint": "Fiat-fixe: Le montant fiat reste le même. XMR-fixe: Le montant XMR reste le même.",
|
||||||
"shippingAvailable": "Livraison disponible",
|
"shippingAvailable": "Livraison disponible",
|
||||||
|
"shippingCost": "Frais de livraison",
|
||||||
|
"shippingCostPlaceholder": "ex. 5.00",
|
||||||
"location": "Emplacement",
|
"location": "Emplacement",
|
||||||
"locationPlaceholder": "Ville, code postal ou adresse",
|
"locationPlaceholder": "Ville, code postal ou adresse",
|
||||||
"locationHint": "Choisissez l'emplacement de votre annonce",
|
"locationHint": "Choisissez l'emplacement de votre annonce",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const CACHE_NAME = 'dgray-v32';
|
const CACHE_NAME = 'dgray-v34';
|
||||||
const STATIC_ASSETS = [
|
const STATIC_ASSETS = [
|
||||||
'/',
|
'/',
|
||||||
'/index.html',
|
'/index.html',
|
||||||
|
|||||||
Reference in New Issue
Block a user