generated from boboko/starter
58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
import { Controller } from '@hotwired/stimulus'
|
|
import { csrfToken } from './csrf'
|
|
|
|
// Sits on an <x-checkout::add-to-cart> <form>. Submits the line to the cart
|
|
// via fetch and hands the server-rendered cart body to the drawer through the
|
|
// `bbk-cart:changed` window event. No DOM building here — the drawer
|
|
// (bbk-cart-controller) owns rendering.
|
|
export default class extends Controller {
|
|
static targets = ['error']
|
|
|
|
async add(event) {
|
|
event.preventDefault()
|
|
|
|
const form = this.element
|
|
const submit = form.querySelector('[type="submit"]')
|
|
|
|
this.clearError()
|
|
form.setAttribute('data-bbk-add-to-cart-state', 'loading')
|
|
if (submit) submit.disabled = true
|
|
|
|
try {
|
|
const response = await fetch(form.action, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRF-TOKEN': csrfToken(),
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
Accept: 'application/json',
|
|
},
|
|
body: new FormData(form),
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const data = await response.json().catch(() => null)
|
|
this.showError(data?.error)
|
|
return
|
|
}
|
|
|
|
window.dispatchEvent(new CustomEvent('bbk-cart:changed', {
|
|
detail: { html: await response.text() },
|
|
}))
|
|
} finally {
|
|
form.removeAttribute('data-bbk-add-to-cart-state')
|
|
if (submit) submit.disabled = false
|
|
}
|
|
}
|
|
|
|
showError(message) {
|
|
if (!this.hasErrorTarget || !message) return
|
|
this.errorTarget.textContent = message
|
|
this.errorTarget.hidden = false
|
|
}
|
|
|
|
clearError() {
|
|
if (!this.hasErrorTarget) return
|
|
this.errorTarget.hidden = true
|
|
}
|
|
}
|