Merge pull request #29 from iantsch/ui-generic-store

Refactor UI to generic store syntax
This commit is contained in:
Mario Zechner 2023-05-28 20:37:45 +02:00 committed by GitHub
commit 35c3bbbcca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 70 deletions

View File

@ -1,3 +1,43 @@
const stores = {
billa: {
name: "Billa",
budgetBrands: ["clever"],
color: "rgb(255 255 225)",
},
dm: {
name: "DM",
budgetBrands: [],
color: "rgb(255 240 230)",
},
hofer: {
name: "Hofer",
budgetBrands: ["milfina"],
color: "rgb(230 230 255)",
},
lidl: {
name: "Lidl",
budgetBrands: ["milbona"],
color: "rgb(255 225 225)",
},
mpreis: {
name: "MPREIS",
budgetBrands: [],
color: "rgb(255 230 230)",
},
spar: {
name: "Spar",
budgetBrands: ["s-budget"],
color: "rgb(225 244 225)",
},
};
const STORE_KEYS = Object.keys(stores);
const BUDGET_BRANDS = [].concat(
...Object
.values(stores)
.map(store => store.budgetBrands)
);
function currentDate() { function currentDate() {
const currentDate = new Date(); const currentDate = new Date();
const year = currentDate.getFullYear(); const year = currentDate.getFullYear();
@ -89,25 +129,16 @@ function removeCart(name) {
} }
function itemToStoreLink(item) { function itemToStoreLink(item) {
if (item.store == "spar") if (STORE_KEYS.includes(item.store)) {
return `<a target="_blank" href="https://www.interspar.at/shop/lebensmittel/search/?q=${encodeURIComponent(item.name)}">${item.name}</a>`; return `<a target="_blank" class="itemname itemname--${item.store}" rel="noopener noreferrer nofollow" href="${item.url}">${item.name}</a>`
if (item.store == "billa") }
return `<a target="_blank" href="https://shop.billa.at/search/results?category=&searchTerm=${encodeURIComponent(item.name)}">${item.name}</a>`; return `<span class="itemname itemname--${item.store} itemname--nolink">${item.name}</span>`;
if (item.store == "hofer")
return `<a target="_blank" href="https://www.roksh.at/hofer/angebot/suche/${encodeURIComponent(item.name)}">${item.name}</a>`;
if (item.store == "dm")
return `<a target="_blank" href="https://www.dm.at/product-p${item.id}.html">${item.name}</a>`;
if (item.store == "lidl")
return `<a target="_blank" href="https://www.lidl.at${item.url}">${item.name}</a>`;
if (item.store == "mpreis")
return `<a target="_blank" href="https://www.mpreis.at/shop/p/${item.id}">${item.name}</a>`;
return item.name;
} }
function itemToDOM(item) { function itemToDOM(item) {
let storeDom = dom("td", item.store); let storeDom = dom("td", item.store);
storeDom.setAttribute("data-label", "Kette"); storeDom.setAttribute("data-label", "Kette");
let nameDom = dom("td", `<div class="itemname">${itemToStoreLink(item)}</div>`); let nameDom = dom("td", `${itemToStoreLink(item)}`);
nameDom.setAttribute("data-label", "Name"); nameDom.setAttribute("data-label", "Name");
let unitDom = dom("td", item.unit ? item.unit : ""); let unitDom = dom("td", item.unit ? item.unit : "");
unitDom.setAttribute("data-label", "Menge"); unitDom.setAttribute("data-label", "Menge");
@ -143,25 +174,7 @@ function itemToDOM(item) {
}); });
} }
let row = dom("tr", ""); let row = dom("tr", "");
switch (item.store) { row.style["background"] = stores[item.store]?.color;
case "billa":
row.style["background"] = "rgb(255 255 225)";
break;
case "spar":
row.style["background"] = "rgb(225 244 225)";
break;
case "hofer":
row.style["background"] = "rgb(230 230 255)";
break;
case "dm":
row.style["background"] = "rgb(255 240 230)";
break;
case "lidl":
row.style["background"] = "rgb(255 225 225)";
break;
case "mpreis":
row.style["background"] = "rgb(255 230 230)";
}
row.appendChild(storeDom); row.appendChild(storeDom);
row.appendChild(nameDom); row.appendChild(nameDom);
row.appendChild(unitDom); row.appendChild(unitDom);
@ -171,7 +184,7 @@ function itemToDOM(item) {
let componentId = 0; let componentId = 0;
function searchItems(items, query, billa, spar, hofer, dm, lidl, mpreis, eigenmarken, minPrice, maxPrice, exact, bio) { function searchItems(items, query, checkedStores, budgetBrands, minPrice, maxPrice, exact, bio) {
query = query.trim(); query = query.trim();
if (query.length < 3) return []; if (query.length < 3) return [];
@ -205,15 +218,13 @@ function searchItems(items, query, billa, spar, hofer, dm, lidl, mpreis, eigenma
} }
if (allFound) { if (allFound) {
const name = item.name.toLowerCase(); const name = item.name.toLowerCase();
if (item.store == "billa" && !billa) continue; if (checkedStores.length && !checkedStores.includes(item.store)) continue;
if (item.store == "spar" && !spar) continue;
if (item.store == "hofer" && !hofer) continue;
if (item.store == "dm" && !dm) continue;
if (item.store == "lidl" && !lidl) continue;
if (item.store == "mpreis" && !mpreis) continue;
if (item.price < minPrice) continue; if (item.price < minPrice) continue;
if (item.price > maxPrice) continue; if (item.price > maxPrice) continue;
if (eigenmarken && !(name.indexOf("clever") == 0 || name.indexOf("s-budget") == 0 || name.indexOf("milfina") == 0)) continue; if (
budgetBrands &&
!BUDGET_BRANDS.some(budgetBrand => name.indexOf(budgetBrand))
) continue;
if (bio && !item.bio) continue; if (bio && !item.bio) continue;
hits.push(item); hits.push(item);
} }
@ -227,16 +238,11 @@ function newSearchComponent(parentElement, items, searched, filter, headerModifi
parentElement.innerHTML = ` parentElement.innerHTML = `
<input id="search-${id}" class="search" type="text" placeholder="Produkte suchen..."> <input id="search-${id}" class="search" type="text" placeholder="Produkte suchen...">
<a id="querylink-${id}" class="hide">Query link</a> <a id="querylink-${id}" class="hide">Query link</a>
<div class="filters"> <div class="filters filters--store">
<label><input id="billa-${id}" type="checkbox" checked="true"> Billa</label> ${STORE_KEYS.map(store => `<label><input id="${store}-${id}" type="checkbox" checked="true">${stores[store].name}</label>`).join(" ")}
<label><input id="spar-${id}" type="checkbox" checked="true"> Spar</label>
<label><input id="hofer-${id}" type="checkbox" checked="true"> Hofer</label>
<label><input id="dm-${id}" type="checkbox" checked="true"> DM</label>
<label><input id="lidl-${id}" type="checkbox" checked="true"> Lidl</label>
<label><input id="mpreis-${id}" type="checkbox" checked="false"> MPREIS</label>
</div> </div>
<div class="filters"> <div class="filters">
<label><input id="eigenmarken-${id}" type="checkbox"> Nur CLEVER / S-BUDGET / MILFINA</label> <label><input id="budgetBrands-${id}" type="checkbox"> Nur ${BUDGET_BRANDS.map(budgetBrand => budgetBrand.toUpperCase()).join(", ")}</label>
<label><input id="bio-${id}" type="checkbox"> Nur Bio</label> <label><input id="bio-${id}" type="checkbox"> Nur Bio</label>
</div> </div>
<div class="filters"> <div class="filters">
@ -252,14 +258,9 @@ function newSearchComponent(parentElement, items, searched, filter, headerModifi
const queryLink = parentElement.querySelector(`#querylink-${id}`); const queryLink = parentElement.querySelector(`#querylink-${id}`);
const exact = parentElement.querySelector(`#exact-${id}`); const exact = parentElement.querySelector(`#exact-${id}`);
const table = parentElement.querySelector(`#result-${id}`); const table = parentElement.querySelector(`#result-${id}`);
const eigenmarken = parentElement.querySelector(`#eigenmarken-${id}`); const budgetBrands = parentElement.querySelector(`#budgetBrands-${id}`);
const bio = parentElement.querySelector(`#bio-${id}`); const bio = parentElement.querySelector(`#bio-${id}`);
const billa = parentElement.querySelector(`#billa-${id}`); const storeCheckboxes = STORE_KEYS.map(store => parentElement.querySelector(`#${store}-${id}`));
const spar = parentElement.querySelector(`#spar-${id}`);
const hofer = parentElement.querySelector(`#hofer-${id}`);
const dm = parentElement.querySelector(`#dm-${id}`);
const lidl = parentElement.querySelector(`#lidl-${id}`);
const mpreis = parentElement.querySelector(`#mpreis-${id}`);
const minPrice = parentElement.querySelector(`#minprice-${id}`); const minPrice = parentElement.querySelector(`#minprice-${id}`);
const maxPrice = parentElement.querySelector(`#maxprice-${id}`); const maxPrice = parentElement.querySelector(`#maxprice-${id}`);
const numResults = parentElement.querySelector(`#numresults-${id}`); const numResults = parentElement.querySelector(`#numresults-${id}`);
@ -269,8 +270,8 @@ function newSearchComponent(parentElement, items, searched, filter, headerModifi
let now = performance.now(); let now = performance.now();
try { try {
hits = searchItems(items, query, hits = searchItems(items, query,
billa.checked, spar.checked, hofer.checked, dm.checked, lidl.checked, mpreis.checked, STORE_KEYS.filter((store, i) => storeCheckboxes[i].checked),
eigenmarken.checked, toNumber(minPrice.value, 0), toNumber(maxPrice.value, 100), exact.checked, bio.checked budgetBrands.checked, toNumber(minPrice.value, 0), toNumber(maxPrice.value, 100), exact.checked, bio.checked
); );
} catch (e) { } catch (e) {
console.log("Query: " + query + "\n" + e.message); console.log("Query: " + query + "\n" + e.message);
@ -320,14 +321,9 @@ function newSearchComponent(parentElement, items, searched, filter, headerModifi
} }
search(searchInput.value); search(searchInput.value);
}); });
eigenmarken.addEventListener("change", () => search(searchInput.value)); budgetBrands.addEventListener("change", () => search(searchInput.value));
bio.addEventListener("change", () => search(searchInput.value)); bio.addEventListener("change", () => search(searchInput.value));
billa.addEventListener("change", () => search(searchInput.value)); storeCheckboxes.map(store => store.addEventListener("change", () => search(searchInput.value)));
spar.addEventListener("change", () => search(searchInput.value));
hofer.addEventListener("change", () => search(searchInput.value));
dm.addEventListener("change", () => search(searchInput.value));
lidl.addEventListener("change", () => search(searchInput.value));
mpreis.addEventListener("change", () => search(searchInput.value));
exact.addEventListener("change", () => search(searchInput.value)); exact.addEventListener("change", () => search(searchInput.value));
minPrice.addEventListener("change", () => search(searchInput.value)); minPrice.addEventListener("change", () => search(searchInput.value));
maxPrice.addEventListener("change", () => search(searchInput.value)); maxPrice.addEventListener("change", () => search(searchInput.value));

View File

@ -8,7 +8,8 @@ exports.getCanonical = function(item, today) {
price: item.data.price.final, price: item.data.price.final,
priceHistory: [{ date: today, price: item.data.price.final }], priceHistory: [{ date: today, price: item.data.price.final }],
unit: item.data.grammagePriceFactor == 1 ? item.data.grammage : "kg", unit: item.data.grammagePriceFactor == 1 ? item.data.grammage : "kg",
bio: item.data.attributes && item.data.attributes.includes("s_bio") bio: item.data.attributes && item.data.attributes.includes("s_bio"),
url: `https://shop.billa.at${item.data.canonicalPath}`
}; };
} }

View File

@ -8,6 +8,7 @@ exports.getCanonical = function(item, today) {
priceHistory: [{ date: today, price: item.price.value }], priceHistory: [{ date: today, price: item.price.value }],
unit: `${item.netQuantityContent} ${item.contentUnit}`, unit: `${item.netQuantityContent} ${item.contentUnit}`,
...(item.brandName === "dmBio" || (item.name ? (item.name.startsWith("Bio ") | item.name.startsWith("Bio-")) : false)) && {bio: true}, ...(item.brandName === "dmBio" || (item.name ? (item.name.startsWith("Bio ") | item.name.startsWith("Bio-")) : false)) && {bio: true},
url: `https://www.dm.at/product-p${item.gtin}.html`
}; };
} }

View File

@ -7,7 +7,8 @@ exports.getCanonical = function(item, today) {
price: item.Price, price: item.Price,
priceHistory: [{ date: today, price: item.Price }], priceHistory: [{ date: today, price: item.Price }],
unit: `${item.Unit} ${item.UnitType}`, unit: `${item.Unit} ${item.UnitType}`,
bio: item.IsBio bio: item.IsBio,
url: `https://www.roksh.at/hofer/produkte/${item.CategorySEOName}/${item.SEOName}`
}; };
} }

View File

@ -8,7 +8,7 @@ exports.getCanonical = function(item, today) {
price: item.price.price, price: item.price.price,
priceHistory: [{ date: today, price: item.price.price }], priceHistory: [{ date: today, price: item.price.price }],
unit: item.price.basePrice?.text ?? "", unit: item.price.basePrice?.text ?? "",
url: item.canonicalUrl url: `https://www.lidl.at${item.canonicalUrl}`
}; };
} }

View File

@ -7,7 +7,8 @@ exports.getCanonical = function(item, today) {
price: item.prices[0].presentationPrice.effectiveAmount, price: item.prices[0].presentationPrice.effectiveAmount,
priceHistory: [{ date: today, price: item.prices[0].presentationPrice.effectiveAmount }], priceHistory: [{ date: today, price: item.prices[0].presentationPrice.effectiveAmount }],
unit: `${item.prices[0].presentationPrice.measurementUnit.quantity} ${item.prices[0].presentationPrice.measurementUnit.unitCode}`, unit: `${item.prices[0].presentationPrice.measurementUnit.quantity} ${item.prices[0].presentationPrice.measurementUnit.unitCode}`,
bio: item.mixins.mpreisAttributes.properties?.includes('BIO') bio: item.mixins.mpreisAttributes.properties?.includes('BIO'),
url: `https://www.mpreis.at/shop/p/${item.code}`
}; };
} }

View File

@ -19,7 +19,8 @@ exports.getCanonical = function(item, today) {
price, price,
priceHistory: [{ date: today, price }], priceHistory: [{ date: today, price }],
unit, unit,
bio: item.masterValues.biolevel === "Bio" bio: item.masterValues.biolevel === "Bio",
url: `https://www.interspar.at/shop/lebensmittel${item.masterValues.url}`
}; };
} }