Backend endpoint makes it easier consume for graph.

New endpoint has the data aggregated so we don't need to do as much in
js.
Also added simple year select when we have data spanning multiple years.
This commit is contained in:
2021-02-18 23:11:48 +01:00
parent d9de155174
commit 7234c2fbba

View File

@@ -2,19 +2,95 @@
<div class="chart"> <div class="chart">
<canvas ref="purchase-chart" width="100" height="50"></canvas> <canvas ref="purchase-chart" width="100" height="50"></canvas>
<div ref="chartjsLegend" class="chartjsLegend"></div> <div ref="chartjsLegend" class="chartjsLegend"></div>
<div class="year-select" v-if="years.length">
<button
class="vin-button small"
v-for="year in years"
:class="{ active: yearSelected == year }"
@click="yearFilterClicked(year)"
>
{{ year }}
</button>
</div>
</div> </div>
</template> </template>
<script> <script>
import Chartjs from "chart.js"; import Chartjs from "chart.js";
import { chartPurchaseByColor } from "@/api";
export default { export default {
data() {
return {
lotteries: [],
years: [],
yearSelected: undefined,
chart: undefined
};
},
async mounted() { async mounted() {
let canvas = this.$refs["purchase-chart"].getContext("2d"); let canvas = this.$refs["purchase-chart"].getContext("2d");
let response = await chartPurchaseByColor(); this.lotteries = await this.chartPurchaseByColor();
let labels = []; if (this.lotteries?.length) this.years = [...new Set(this.lotteries.map(lot => lot.date.slice(0, 4)))];
const dataset = this.calculateChartDatapoints();
let chartData = {
labels: dataset.labels,
datasets: [dataset.blue, dataset.green, dataset.red, dataset.yellow]
};
this.chart = new Chart(canvas, {
type: "line",
data: chartData,
options: {
maintainAspectRatio: false,
animation: {
duration: 0 // general animation time
},
title: {
display: true,
text: "Antall kjøpt",
fontSize: 20
},
legend: {
display: true,
boxWidth: 3,
usePointStyle: true,
borderRadius: 10,
labels: {
padding: 12,
boxWidth: 20,
usePointStyle: true
}
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
});
},
methods: {
async yearFilterClicked(year) {
this.yearSelected = this.yearSelected === year ? null : year;
this.lotteries = await this.chartPurchaseByColor();
const dataset = this.calculateChartDatapoints();
let chartData = {
labels: dataset.labels,
datasets: [dataset.blue, dataset.green, dataset.red, dataset.yellow]
};
this.chart.data = chartData;
this.chart.update();
},
setupDataset() {
let blue = { let blue = {
label: "Blå", label: "Blå",
borderColor: "#57d2fb", borderColor: "#57d2fb",
@@ -44,86 +120,39 @@ export default {
data: [] data: []
}; };
if (response.length == 1) { return {
labels.push(""); labels: [""],
blue.data.push(0); blue,
yellow.data.push(0); green,
red.data.push(0); red,
green.data.push(0); yellow
}
let highestNumber = 0;
for (let i = 0; i < response.length; i++) {
let thisDate = response[i];
let dateObject = new Date(thisDate.date);
labels.push(this.getPrettierDateString(dateObject));
blue.data.push(thisDate.blue);
yellow.data.push(thisDate.yellow);
red.data.push(thisDate.red);
green.data.push(thisDate.green);
if (thisDate.blue > highestNumber) {
highestNumber = thisDate.blue;
}
if (thisDate.yellow > highestNumber) {
highestNumber = thisDate.yellow;
}
if (thisDate.green > highestNumber) {
highestNumber = thisDate.green;
}
if (thisDate.red > highestNumber) {
highestNumber = thisDate.red;
}
}
let datasets = [blue, yellow, green, red];
let chartdata = {
labels: labels,
datasets: datasets
}; };
let chart = new Chart(canvas, {
type: "line",
data: chartdata,
options: {
maintainAspectRatio: false,
animation: {
duration: 0 // general animation time
}, },
title: { calculateChartDatapoints() {
display: true, let dataset = this.setupDataset();
text: "Antall kjøpt",
fontSize: 20 this.lotteries.map(lottery => {
}, const date = new Date(lottery.date);
legend: { dataset.labels.push(this.getPrettierDateString(date));
display: true,
boxWidth: 3, dataset.blue.data.push(lottery.blue);
usePointStyle: true, dataset.green.data.push(lottery.green);
borderRadius: 10, dataset.red.data.push(lottery.red);
labels: { dataset.yellow.data.push(lottery.yellow);
padding: 12,
boxWidth: 20,
usePointStyle: true
}
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
suggestedMax: highestNumber + 5
}
}
]
}
}
}); });
return dataset;
},
chartPurchaseByColor() {
const url = new URL("/api/lotteries", window.location);
if (this.yearSelected != null) url.searchParams.set("year", this.yearSelected);
return fetch(url.href)
.then(resp => resp.json())
.then(response => response.lotteries);
}, },
methods: {
getPrettierDateString(date) { getPrettierDateString(date) {
return `${this.pad(date.getDate())}.${this.pad( return `${this.pad(date.getDate())}.${this.pad(date.getMonth() + 1)}.${this.pad(date.getYear() - 100)}`;
date.getMonth() + 1
)}.${this.pad(date.getYear() - 100)}`;
}, },
pad(num) { pad(num) {
if (num < 10) { if (num < 10) {
@@ -136,11 +165,19 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../styles/media-queries.scss"; @import "@/styles/media-queries.scss";
.chart { .chart {
height: 40vh; height: 40vh;
max-height: 500px; max-height: 500px;
width: 100%; width: 100%;
} }
.year-select {
margin-top: 1rem;
button:not(:first-of-type) {
margin-left: 0.5rem;
}
}
</style> </style>