2021-06-01 21:33:49 +00:00
|
|
|
import { Controller } from 'stimulus'
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mantiene el stock actualizado, consultando a la API.
|
|
|
|
*
|
|
|
|
* * Obtiene todas las variantes en el controlador
|
|
|
|
* * Consulta a la API
|
|
|
|
* * Actualiza stock y precio
|
|
|
|
* * Deshabilita botón si no está en stock
|
|
|
|
*/
|
|
|
|
export default class extends Controller {
|
|
|
|
static targets = [ 'product' ]
|
|
|
|
|
|
|
|
async connect () {
|
2021-10-27 18:47:58 +00:00
|
|
|
const all_skus = this.skus
|
2021-06-01 21:33:49 +00:00
|
|
|
|
2021-10-27 18:47:58 +00:00
|
|
|
if (all_skus.length === 0) return
|
2021-06-01 21:33:49 +00:00
|
|
|
|
2021-10-27 18:47:58 +00:00
|
|
|
// El paginado es para prevenir que la petición se haga muy grande y
|
|
|
|
// falle entera.
|
|
|
|
const pages = Math.ceil(all_skus.length / this.per_page)
|
|
|
|
|
|
|
|
let start = 0
|
|
|
|
let end = this.per_page
|
|
|
|
|
|
|
|
for (let local_page = 1; local_page <= pages; local_page++) {
|
|
|
|
const skus = all_skus.slice(start, end).join(',')
|
2021-06-01 21:33:49 +00:00
|
|
|
|
2021-10-27 18:47:58 +00:00
|
|
|
start = this.per_page * local_page
|
|
|
|
end = start + this.per_page
|
2021-06-01 21:33:49 +00:00
|
|
|
|
2021-10-27 18:47:58 +00:00
|
|
|
const filter = { skus }
|
|
|
|
let response = await window.spree.products.list({ filter })
|
2021-06-01 21:33:49 +00:00
|
|
|
|
|
|
|
if (response.isFail()) {
|
|
|
|
console.error(response.fail())
|
2021-10-27 18:47:58 +00:00
|
|
|
return
|
2021-06-01 21:33:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.update_local_products(response.success().data)
|
2021-10-27 18:47:58 +00:00
|
|
|
|
|
|
|
// Recorrer todas las páginas
|
|
|
|
// XXX: Podríamos usar next pero la página 1 siempre se devuelve a
|
|
|
|
// sí misma y entraríamos en un loop infinito.
|
|
|
|
for (let page = 2; page <= response.success().meta.total_pages; page++) {
|
|
|
|
response = await window.spree.products.list({ filter, page })
|
|
|
|
|
|
|
|
if (response.isFail()) {
|
|
|
|
console.error(response.fail())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
this.update_local_products(response.success().data)
|
|
|
|
}
|
2021-06-01 21:33:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* La lista de todas las variantes incluidas en el controlador que no
|
2021-10-27 18:47:58 +00:00
|
|
|
* estén vacías. Usamos los SKUs porque no tenemos forma de filtrar
|
|
|
|
* por ID.
|
2021-06-01 21:33:49 +00:00
|
|
|
*
|
|
|
|
* @return [Array]
|
|
|
|
*/
|
2021-10-27 18:47:58 +00:00
|
|
|
get skus () {
|
|
|
|
return [...new Set(this.productTargets.map(p=> p.dataset.sku).filter(x => x.length > 0))]
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* La cantidad de productos por página que vamos a pedir
|
|
|
|
*/
|
|
|
|
get per_page () {
|
|
|
|
if (!this._per_page) {
|
|
|
|
this._per_page = parseInt(this.element.dataset.perPage)
|
|
|
|
if (isNaN(this._per_page)) this._per_page = 100
|
|
|
|
}
|
2021-06-01 21:33:49 +00:00
|
|
|
|
2021-10-27 18:47:58 +00:00
|
|
|
return this._per_page
|
2021-06-01 21:33:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Los productos pueden estar duplicados así que buscamos todos.
|
|
|
|
*/
|
|
|
|
update_local_products (products) {
|
2021-10-27 18:47:58 +00:00
|
|
|
for (const local of this.productTargets) {
|
|
|
|
for (const product of products.filter(p => local.dataset.cartVariantId === p.relationships.default_variant.data.id)) {
|
2021-06-01 21:33:49 +00:00
|
|
|
local.dataset.cartInStock = product.attributes.in_stock
|
|
|
|
local.dataset.cartPrice = product.attributes.price
|
|
|
|
|
|
|
|
local.querySelectorAll('[data-stock-add]').forEach(button => button.disabled = !product.attributes.in_stock)
|
2021-10-27 18:47:58 +00:00
|
|
|
local.querySelectorAll('[data-stock-price]').forEach(price => price.innerText = parseInt(product.attributes.price))
|
|
|
|
local.querySelectorAll('[data-stock-currency]').forEach(currency => currency.innerText = product.attributes.currency)
|
2021-06-01 21:33:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|