diff --git a/site/index.html b/site/index.html
index 84ebfda..858df8d 100644
--- a/site/index.html
+++ b/site/index.html
@@ -11,12 +11,12 @@
+
Heisse Preise
-
Heisse Preise
diff --git a/site/style.css b/site/style.css
index 6b75dba..71e01ee 100644
--- a/site/style.css
+++ b/site/style.css
@@ -1,11 +1,17 @@
* {
- box-sizing: border-box;
+ box-sizing: border-box;
}
body {
margin: 0;
padding: 1em;
- font-family: sans-serif;
+ font-family: Helvetica;
+ background: #f5f5f5;
+ color: #393939;
+}
+
+a {
+ color: #c9543a;
}
.column {
@@ -15,6 +21,7 @@ body {
align-items: center;
margin: 0 auto;
width: 100%;
+ max-width: 1000px;
}
.search {
@@ -28,33 +35,97 @@ body {
margin-bottom: 1em;
}
+input {
+ border: 2px solid;
+ padding: 0.4em;
+ border-color: #ee907b;
+ accent-color: #c9543a;
+}
+
input[type="number"] {
- max-width: 3em;
+ max-width: 6em;
+ border: 2px solid;
+ padding: 0.4em;
+ border-color: #ee907b;
+}
+
+h2 {
+ background-color: #c9543a;
+ color: white;
+ width: 100%;
+ text-transform: uppercase;
+ text-align: center;
+ padding: 0.5em;
+ margin-top: 0;
}
table {
border-collapse: collapse;
- border: 1px solid;
+ border: 0px;
margin-top: 1em;
}
th {
- border: 1px solid;
padding: 0.2em;
- background: #aaa;
+ text-align: left;
+ background: #c9543a;
+ color: white;
+ border: 0px;
+}
+
+th:nth-child(1) {
+ text-align: center;
+}
+
+th:nth-child(3) {
+ text-align: right;
+ padding: 0.7em;
+}
+
+th:nth-child(4) {
+ text-align: center;
+ padding: 0.6em;
}
tr {
border-collapse: collapse;
border: 1px solid #ddd;
+ border-left: 0px;
+ border-right: 0px;
}
td {
padding: 0.2em;
}
-th {
- text-align: left;
+td a {
+ color: #393939;
+ text-decoration: none;
+}
+
+td:nth-child(1) {
+ text-align: center;
+ padding: 0.5em;
+}
+
+td:nth-child(2) {
+ background-color: white;
+ padding: 0.4em;
+}
+
+td:nth-child(3) {
+ background-color: white;
+ font-size: small;
+ text-align: right;
+ padding-right: 0.7em;
+}
+
+td:nth-child(4) {
+ padding-left: 0.5em;
+}
+
+td:nth-child(4):before {
+ content: "€ "
}
.itemname {
@@ -88,51 +159,67 @@ th {
@media screen and (max-width: 600px) {
table {
- border: 0;
+ border: 0;
}
table thead {
- border: none;
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
+ border: none;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
}
table tr {
- display: block;
- margin-bottom: .625em;
+ display: block;
+ margin-bottom: .625em;
}
table td {
- border-bottom: 1px solid #ddd;
- padding-left: calc(65px + 1.2em);
- position: relative;
- display: block;
+ border-bottom: 1px solid #ddd;
+ padding: 0 0 0 0 !important;
+ padding-left: calc(65px + 1.2em) !important;
+ position: relative;
+ display: block;
}
table td::before {
- /*
- * aria-label has no advantage, it won't be read inside a table
- content: attr(aria-label);
- */
- content: attr(data-label);
- background-color: #aaa;
- border: 1px solid;
- position: absolute;
- padding: .2em .4em;
- width: 65px;
- height: calc(100% - .4em);
- left: -1px;
- top: -1px;
- text-align: right;
- font-weight: bold;
+ /*
+ * aria-label has no advantage, it won't be read inside a table
+ content: attr(aria-label);
+ */
+ content: attr(data-label);
+ background-color: #c9543a;
+ color: white;
+ border: 0px;
+ position: absolute;
+ padding: .1em .4em;
+ width: 65px;
+ height: calc(100%);
+ left: -1px;
+ top: -1px;
+ text-align: right;
+ font-weight: bold;
+ font-size: medium;
+ }
+
+ td:nth-child(1) {
+ text-align: center;
+ font-size: medium;
+ padding: 0.5em;
+ }
+
+ td:nth-child(3) {
+ background-color: white;
+ font-size: medium;
+ text-align: left;
+ padding-right: 0.7em;
}
table td:last-child {
- border-bottom: 0;
+ border-bottom: 0;
}
- }
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/site/utils.js b/site/utils.js
index 0d60321..cf03b68 100644
--- a/site/utils.js
+++ b/site/utils.js
@@ -375,7 +375,15 @@ function showChart(canvasDom, items) {
},
options: {
responsive: true,
- aspectRation: 16 / 9
+ aspectRation: 16 / 9,
+ scales: {
+ y: {
+ title: {
+ display: true,
+ text: "EURO"
+ }
+ }
+ }
}
});
}
diff --git a/stores/spar.js b/stores/spar.js
index 469145a..cda8502 100644
--- a/stores/spar.js
+++ b/stores/spar.js
@@ -14,6 +14,7 @@ exports.getCanonical = function(item, today) {
}
return {
id: item.masterValues["code-internal"],
+ sparId: item.masterValues["product-number"],
name: item.masterValues.title + " " + item.masterValues["short-description"],
price,
priceHistory: [{ date: today, price }],
diff --git a/stuff.js b/stuff.js
index df963ef..a4c5043 100644
--- a/stuff.js
+++ b/stuff.js
@@ -150,4 +150,81 @@ function fixSparHistoricalData(dataDir) {
}
}
-// momentumCartConversion();
\ No newline at end of file
+const nReadlines = require('n-readlines');
+
+function convertDossierData(dataDir, file) {
+ console.log(`Converting ${file}`);
+ const lookup = {};
+ for (item of JSON.parse(fs.readFileSync(`${dataDir}/latest-canonical.json`))) {
+ lookup[item.store + item.id] = item;
+ if (item.sparId)
+ lookup[item.store + "-" + item.sparId] = item;
+ }
+
+ const lines = new nReadlines(file);
+
+ const itemsPerDate = {};
+ let line = null;
+ const store = file.indexOf("spar") == 0 ? "spar" : "billa";
+ lines.next()
+ let itemsTotal = 0;
+ let notFound = 0;
+ while(line = lines.next()) {
+ itemsTotal++;
+ const tokens = line.toString("utf-8").split(";");
+ const dateTokens = tokens[0].split(".");
+ const date = "20" + dateTokens[2] + "-" + dateTokens[1] + "-" + dateTokens[0];
+ const producer = tokens[5];
+ const name = tokens[3];
+ const unit = tokens[6];
+ const price = Number.parseFloat(tokens[7].replace("€", "").trim().replace(",", "."));
+ const id = tokens[4].replace("ARTIKELNUMMER: ", "").replace("Art. Nr.: ", "");
+ let item = lookup[store + id];
+ if (!item)
+ item = lookup[store + "-" + id]
+ if (!item) {
+ // console.log("Couldn't find item " + name);
+ notFound++;
+ continue;
+ }
+ let items = itemsPerDate[date];
+ if (!items) itemsPerDate[date] = items = [];
+ if (store == "spar") {
+ items.push({
+ masterValues: {
+ "code-internal": item.id,
+ "product-number": id,
+ price,
+ title: producer,
+ "short-description": name,
+ "short-description-3": unit,
+ bioLevel: ""
+ }
+ });
+ } else {
+ items.push({
+ data: {
+ articleId: id,
+ name: name,
+ price: {
+ final: price
+ },
+ grammagePriceFactor: 1,
+ grammage: unit,
+ }
+ })
+ }
+ }
+ console.log("total: " + itemsTotal);
+ console.log("not found: " + notFound);
+
+ const dates = Object.keys(itemsPerDate).sort((a, b) => b.localeCompare(a));
+ for (date of dates) {
+ fs.writeFileSync(`${dataDir}/${store}-${date}.json`, JSON.stringify(itemsPerDate[date], null, 2));
+ }
+ console.log(`Wrote files for ${file}`);
+}
+// momentumCartConversion();
+
+convertDossierData("data", "spar-2020.csv");
+convertDossierData("data", "billa-2020.csv");
\ No newline at end of file