diff --git a/js/components/pages/page-about.js b/js/components/pages/page-about.js index bf321bf..335cc22 100644 --- a/js/components/pages/page-about.js +++ b/js/components/pages/page-about.js @@ -2,12 +2,14 @@ import { getCurrentLanguage, i18n } from '../../i18n.js' class PageAbout extends HTMLElement { connectedCallback() { + this._unsubs = [] this.render() - this.unsubscribe = i18n.subscribe(() => this.render()) + this._unsubs.push(i18n.subscribe(() => this.render())) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] } getContent(lang) { diff --git a/js/components/pages/page-contact.js b/js/components/pages/page-contact.js index fb3cfb5..b95c728 100644 --- a/js/components/pages/page-contact.js +++ b/js/components/pages/page-contact.js @@ -2,12 +2,14 @@ import { getCurrentLanguage, i18n } from '../../i18n.js' class PageContact extends HTMLElement { connectedCallback() { + this._unsubs = [] this.render() - this.unsubscribe = i18n.subscribe(() => this.render()) + this._unsubs.push(i18n.subscribe(() => this.render())) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] } getContent(lang) { diff --git a/js/components/pages/page-create.js b/js/components/pages/page-create.js index 73429d1..8c0d40c 100644 --- a/js/components/pages/page-create.js +++ b/js/components/pages/page-create.js @@ -72,6 +72,8 @@ class PageCreate extends HTMLElement { } async connectedCallback() { + this._unsubs = [] + // Check if logged in if (!auth.isLoggedIn()) { this.showLoginRequired() @@ -90,7 +92,7 @@ class PageCreate extends HTMLElement { await this.loadCategories() await this.checkAccountStatus() this.render() - this.unsubscribe = i18n.subscribe(() => this.render()) + this._unsubs.push(i18n.subscribe(() => this.render())) } async loadExistingListing() { @@ -165,7 +167,7 @@ class PageCreate extends HTMLElement { this.hasDraft = !!localStorage.getItem(STORAGE_KEY) await this.loadCategories() this.render() - this.unsubscribe = i18n.subscribe(() => this.render()) + this._unsubs.push(i18n.subscribe(() => this.render())) }, { once: true }) authModal.addEventListener('close', () => { // If closed without login, go back @@ -206,7 +208,8 @@ class PageCreate extends HTMLElement { } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] } render() { diff --git a/js/components/pages/page-favorites.js b/js/components/pages/page-favorites.js index cc67341..7d5d391 100644 --- a/js/components/pages/page-favorites.js +++ b/js/components/pages/page-favorites.js @@ -15,15 +15,16 @@ class PageFavorites extends HTMLElement { } connectedCallback() { + this._unsubs = [] this.render() this.loadFavorites() - this.unsubscribe = i18n.subscribe(() => this.render()) - this.favUnsubscribe = favoritesService.subscribe(() => this.loadFavorites()) + this._unsubs.push(i18n.subscribe(() => this.render())) + this._unsubs.push(favoritesService.subscribe(() => this.loadFavorites())) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() - if (this.favUnsubscribe) this.favUnsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] } async loadFavorites() { diff --git a/js/components/pages/page-home.js b/js/components/pages/page-home.js index e7290fe..02f3214 100644 --- a/js/components/pages/page-home.js +++ b/js/components/pages/page-home.js @@ -40,25 +40,26 @@ class PageHome extends HTMLElement { this.setupEventListeners() this.setupPullToRefresh() this.loadListings() - this.unsubscribe = i18n.subscribe(() => { + this._unsubs = [] + this._unsubs.push(i18n.subscribe(() => { this.updateTextContent() - }) + })) // Re-render listings on auth change to show owner badges - this.authUnsubscribe = auth.subscribe(() => { + this._unsubs.push(auth.subscribe(() => { const container = this.querySelector('#listings-container') if (container) { container.innerHTML = this.renderListings() } - }) + })) // Listen for URL changes (back/forward navigation) window.addEventListener('hashchange', this._onHashChange) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() - if (this.authUnsubscribe) this.authUnsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] window.removeEventListener('hashchange', this._onHashChange) } diff --git a/js/components/pages/page-listing.js b/js/components/pages/page-listing.js index b7c5921..d14e12f 100644 --- a/js/components/pages/page-listing.js +++ b/js/components/pages/page-listing.js @@ -23,14 +23,16 @@ class PageListing extends HTMLElement { connectedCallback() { this.listingId = this.dataset.id + this._unsubs = [] this.render() this.loadListing() - this.unsubscribe = i18n.subscribe(() => this.render()) + this._unsubs.push(i18n.subscribe(() => this.render())) window.addEventListener('currency-changed', this.handleCurrencyChange) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] window.removeEventListener('currency-changed', this.handleCurrencyChange) this.resetMetaTags() } diff --git a/js/components/pages/page-messages.js b/js/components/pages/page-messages.js index 3f3eaf2..88eaae1 100644 --- a/js/components/pages/page-messages.js +++ b/js/components/pages/page-messages.js @@ -23,19 +23,20 @@ class PageMessages extends HTMLElement { this.render() this.loadConversations() - this.unsubscribe = i18n.subscribe(() => this.render()) - this.authUnsubscribe = auth.subscribe(() => { + this._unsubs = [] + this._unsubs.push(i18n.subscribe(() => this.render())) + this._unsubs.push(auth.subscribe(() => { this.isLoggedIn = auth.isLoggedIn() if (!this.isLoggedIn) { window.location.hash = '#/' } - }) + })) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() - if (this.authUnsubscribe) this.authUnsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] } async loadConversations() { diff --git a/js/components/pages/page-my-listings.js b/js/components/pages/page-my-listings.js index 7871c83..a133faa 100644 --- a/js/components/pages/page-my-listings.js +++ b/js/components/pages/page-my-listings.js @@ -13,6 +13,7 @@ class PageMyListings extends HTMLElement { this.loading = true this.error = null this.isLoggedIn = false + this._handleClick = this.handleDelegatedClick.bind(this) } connectedCallback() { @@ -25,23 +26,42 @@ class PageMyListings extends HTMLElement { this.render() this.loadMyListings() + this.addEventListener('click', this._handleClick) - this.unsubscribe = i18n.subscribe(() => this.render()) - this.authUnsubscribe = auth.subscribe(() => { + this._unsubs = [] + this._unsubs.push(i18n.subscribe(() => this.render())) + this._unsubs.push(auth.subscribe(() => { this.isLoggedIn = auth.isLoggedIn() if (!this.isLoggedIn) { window.location.hash = '#/' } - }) + })) } disconnectedCallback() { - if (this.unsubscribe) this.unsubscribe() - if (this.authUnsubscribe) this.authUnsubscribe() + this._unsubs.forEach(fn => fn()) + this._unsubs = [] + this.removeEventListener('click', this._handleClick) this.stopPolling() } + handleDelegatedClick(e) { + const toggleBtn = e.target.closest('.btn-toggle-status') + if (toggleBtn) { + e.preventDefault() + e.stopPropagation() + this.toggleListingStatus(toggleBtn.dataset.id, toggleBtn.dataset.status) + return + } + const deleteBtn = e.target.closest('.btn-delete-listing') + if (deleteBtn) { + e.preventDefault() + e.stopPropagation() + this.deleteListing(deleteBtn.dataset.id) + } + } + startPolling() { this.stopPolling() const hasPending = this.listings.some(l => @@ -221,11 +241,9 @@ class PageMyListings extends HTMLElement { const locationName = listing.location?.name || '' const statusBadge = this.getStatusBadge(listing) - const paidActive = listingsService.isPaidAndActive(listing) const isPublished = listing.status === 'published' - const isDraftPaid = listing.status === 'draft' && paidActive let toggleBtn = '' - if (isPublished || isDraftPaid) { + if (listingsService.canTogglePublish(listing)) { const label = isPublished ? t('myListings.unpublish') : t('myListings.republish') toggleBtn = /* html */`