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() { const all_skus = this.skus; if (all_skus.length === 0) return; // 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(","); start = this.per_page * local_page; end = start + this.per_page; const filter = { skus }; let response = await window.spree.products.list({ filter }); if (response.isFail()) { console.error(response.fail()); return; } this.update_local_products(response.success().data); // 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); } } } /* * La lista de todas las variantes incluidas en el controlador que no * estén vacías. Usamos los SKUs porque no tenemos forma de filtrar * por ID. * * @return [Array] */ 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; } return this._per_page; } /* * Los productos pueden estar duplicados así que buscamos todos. */ update_local_products(products) { for (const local of this.productTargets) { for (const product of products.filter( (p) => local.dataset.cartVariantId === p.relationships.default_variant.data.id )) { 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) ); 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) ); } } } }