account pages: login, order history, order details, account details, wishlist

This commit is contained in:
elvira
2026-09-24 17:27:58 +03:00
parent 580adac33a
commit cf3681260b
42 changed files with 1972 additions and 15 deletions
+2
View File
@@ -19,6 +19,7 @@ import RangeSliderController from './range-slider-controller'
import StarRatingController from './star-rating-controller'
import TabLinkController from './tab-link-controller'
import TabsController from './tabs-controller'
import WishlistController from './wishlist-controller'
export function registerControllers(application) {
application.register('appear', AppearController)
@@ -37,4 +38,5 @@ export function registerControllers(application) {
application.register('star-rating', StarRatingController)
application.register('tab-link', TabLinkController)
application.register('tabs', TabsController)
application.register('wishlist', WishlistController)
}
@@ -0,0 +1,42 @@
import { Controller } from '@hotwired/stimulus'
// Heart toggle (x-wishlist-button). Posts the form with fetch and reflects the
// server's answer on aria-pressed, which the CSS uses to swap the outline and
// filled heart. If the request fails, falls back to a normal form submit.
export default class extends Controller {
static targets = ['button', 'status']
static values = {
addLabel: String,
removeLabel: String,
addedMessage: String,
removedMessage: String,
}
async toggle(event) {
event.preventDefault()
if (this.busy) return
this.busy = true
try {
const response = await fetch(this.element.action, {
method: 'POST',
headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
body: new FormData(this.element),
})
if (!response.ok) throw new Error(`Wishlist toggle failed: ${response.status}`)
const { active } = await response.json()
this.buttonTarget.setAttribute('aria-pressed', active ? 'true' : 'false')
this.buttonTarget.setAttribute('aria-label', active ? this.removeLabelValue : this.addLabelValue)
this.statusTarget.textContent = active ? this.addedMessageValue : this.removedMessageValue
} catch {
this.element.submit()
} finally {
this.busy = false
}
}
}