sutty-base-jekyll-theme/_packs/controllers/stock_controller.js

119 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

2021-11-22 17:51:50 +00:00
import { Controller } from "stimulus";
2021-06-01 21:33:49 +00:00
/*
* 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 {
2021-11-22 17:51:50 +00:00
static targets = ["product"];
2021-06-01 21:33:49 +00:00
2021-11-22 17:51:50 +00:00
async connect() {
const all_skus = this.skus;
2021-06-01 21:33:49 +00:00
2021-11-22 17:51:50 +00:00
if (all_skus.length === 0) return;
2021-06-01 21:33:49 +00:00
// El paginado es para prevenir que la petición se haga muy grande y
// falle entera.
2021-11-22 17:51:50 +00:00
const pages = Math.ceil(all_skus.length / this.per_page);
2021-11-22 17:51:50 +00:00
let start = 0;
let end = this.per_page;
for (let local_page = 1; local_page <= pages; local_page++) {
2021-11-22 17:51:50 +00:00
const skus = all_skus.slice(start, end).join(",");
2021-06-01 21:33:49 +00:00
2021-11-22 17:51:50 +00:00
start = this.per_page * local_page;
end = start + this.per_page;
2021-06-01 21:33:49 +00:00
2021-11-22 17:51:50 +00:00
const filter = { skus };
let response = await window.spree.products.list({ filter });
2021-06-01 21:33:49 +00:00
if (response.isFail()) {
2021-11-22 17:51:50 +00:00
console.error(response.fail());
return;
2021-06-01 21:33:49 +00:00
}
2021-11-22 17:51:50 +00:00
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++) {
2021-11-22 17:51:50 +00:00
response = await window.spree.products.list({ filter, page });
if (response.isFail()) {
2021-11-22 17:51:50 +00:00
console.error(response.fail());
continue;
}
2021-11-22 17:51:50 +00:00
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
* 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-11-22 17:51:50 +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
*/
2021-11-22 17:51:50 +00:00
get per_page() {
if (!this._per_page) {
2021-11-22 17:51:50 +00:00
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-11-22 17:51:50 +00:00
return this._per_page;
2021-06-01 21:33:49 +00:00
}
/*
* Los productos pueden estar duplicados así que buscamos todos.
*/
2021-11-22 17:51:50 +00:00
update_local_products(products) {
for (const local of this.productTargets) {
2021-11-22 17:51:50 +00:00
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)
);
2021-06-01 21:33:49 +00:00
}
}
}
}