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:
		| @@ -2,19 +2,95 @@ | ||||
|   <div class="chart"> | ||||
|     <canvas ref="purchase-chart" width="100" height="50"></canvas> | ||||
|     <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> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import Chartjs from "chart.js"; | ||||
| import { chartPurchaseByColor } from "@/api"; | ||||
|  | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
|       lotteries: [], | ||||
|       years: [], | ||||
|       yearSelected: undefined, | ||||
|       chart: undefined | ||||
|     }; | ||||
|   }, | ||||
|   async mounted() { | ||||
|     let canvas = this.$refs["purchase-chart"].getContext("2d"); | ||||
|  | ||||
|     let response = await chartPurchaseByColor(); | ||||
|     let labels = []; | ||||
|     this.lotteries = await this.chartPurchaseByColor(); | ||||
|     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 = { | ||||
|         label: "Blå", | ||||
|         borderColor: "#57d2fb", | ||||
| @@ -44,86 +120,39 @@ export default { | ||||
|         data: [] | ||||
|       }; | ||||
|  | ||||
|     if (response.length == 1) { | ||||
|       labels.push(""); | ||||
|       blue.data.push(0); | ||||
|       yellow.data.push(0); | ||||
|       red.data.push(0); | ||||
|       green.data.push(0); | ||||
|     } | ||||
|  | ||||
|     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 | ||||
|       return { | ||||
|         labels: [""], | ||||
|         blue, | ||||
|         green, | ||||
|         red, | ||||
|         yellow | ||||
|       }; | ||||
|     let 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, | ||||
|                 suggestedMax: highestNumber + 5 | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         } | ||||
|       } | ||||
|     calculateChartDatapoints() { | ||||
|       let dataset = this.setupDataset(); | ||||
|  | ||||
|       this.lotteries.map(lottery => { | ||||
|         const date = new Date(lottery.date); | ||||
|         dataset.labels.push(this.getPrettierDateString(date)); | ||||
|  | ||||
|         dataset.blue.data.push(lottery.blue); | ||||
|         dataset.green.data.push(lottery.green); | ||||
|         dataset.red.data.push(lottery.red); | ||||
|         dataset.yellow.data.push(lottery.yellow); | ||||
|       }); | ||||
|  | ||||
|       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) { | ||||
|       return `${this.pad(date.getDate())}.${this.pad( | ||||
|         date.getMonth() + 1 | ||||
|       )}.${this.pad(date.getYear() - 100)}`; | ||||
|       return `${this.pad(date.getDate())}.${this.pad(date.getMonth() + 1)}.${this.pad(date.getYear() - 100)}`; | ||||
|     }, | ||||
|     pad(num) { | ||||
|       if (num < 10) { | ||||
| @@ -136,11 +165,19 @@ export default { | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| @import "../styles/media-queries.scss"; | ||||
| @import "@/styles/media-queries.scss"; | ||||
|  | ||||
| .chart { | ||||
|   height: 40vh; | ||||
|   max-height: 500px; | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .year-select { | ||||
|   margin-top: 1rem; | ||||
|  | ||||
|   button:not(:first-of-type) { | ||||
|     margin-left: 0.5rem; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user