controllers/dashboard/years_controller.js

  1. import { Controller } from "@hotwired/stimulus"
  2. import { subscription } from "~/javascripts/store/mixins/subscription"
  3. /**
  4. * @class Dashboard.YearsController
  5. * @classdesc Stimulus controller that fetches the data to populate the years and months buttons.
  6. * @extends Controller
  7. **/
  8. export default class extends Controller {
  9. static targets = [ "buttonGroup", "button" ]
  10. static values = {
  11. storeId: String,
  12. function: String,
  13. status: String
  14. }
  15. /**
  16. * Subscribe to the store. Setup dataVizData and then fetch years and months data
  17. *
  18. * @instance
  19. * @memberof Dashboard.YearsController
  20. **/
  21. connect() {
  22. subscription(this)
  23. this.subscribe()
  24. if (!this.store("dataVizData")) this.editStore("dataVizData", {})
  25. if (!this.store("yearsAndMonths")) this.yearsAndMonths()
  26. this.reconnect()
  27. }
  28. /**
  29. * Handles a repeated Turbo visit to the dashboard page.
  30. *
  31. * @instance
  32. * @memberof Dashboard.YearsController
  33. **/
  34. reconnect() {
  35. if (this.store("selectedDataVizData")) {
  36. this.storeUpdated("yearsAndMonths", this.storeIdValue)
  37. }
  38. }
  39. /**
  40. * Triggered when the years and months data is loaded. Uses a document fragment to fully create the
  41. * years buttons before removing the load button and adding all the new years buttons. The last button
  42. * is set as selected
  43. *
  44. * @instance
  45. * @memberof Dashboard.YearsController
  46. **/
  47. statusValueChanged() {
  48. if (this.statusValue === "loaded") {
  49. let fragment = document.createDocumentFragment()
  50. this.store("years").forEach(year => {
  51. const buttonClone = this.buttonTarget.cloneNode(false)
  52. const button = fragment.appendChild(buttonClone)
  53. button.innerHTML = year
  54. });
  55. this.buttonTarget.remove()
  56. this.buttonGroupTarget.appendChild(fragment)
  57. this.buttonTargets[this.buttonTargets.length - 1].classList.add("selected")
  58. }
  59. }
  60. /**
  61. * Ignores year if already clicked. Set the months data for the selected year. Set the last month as
  62. * selected in the store and gives the class selected to the clicked year.
  63. *
  64. * @instance
  65. * @memberof Dashboard.YearsController
  66. **/
  67. yearClicked(event) {
  68. if (this.store("yearSelected") === parseInt(event.target.innerHTML)) return
  69. this.editStore("yearSelected", parseInt(event.target.innerHTML))
  70. const yearAndMonths = this.store("yearsAndMonths").find(data => {
  71. return data.year === this.store("yearSelected")
  72. })
  73. this.editStore("months", yearAndMonths.month_numbers)
  74. this.editStore("monthSelected", this.store("months")[this.store("months").length - 1])
  75. this.buttonTargets.forEach(buttonTarget => buttonTarget.classList.remove("selected"))
  76. event.target.classList.add("selected")
  77. }
  78. /**
  79. * Fetch the data for years and months.
  80. *
  81. * @instance
  82. * @memberof Dashboard.YearsController
  83. **/
  84. yearsAndMonths() {
  85. fetch("/.netlify/functions/supabase-get-functions", {
  86. headers: { "Function-Name": this.functionValue }
  87. })
  88. .then(responseCheck => {
  89. if (!responseCheck.ok) { throw Error(responseCheck.status); }
  90. return responseCheck;
  91. })
  92. .then(res => res.json())
  93. .then(yearsAndMonths => {
  94. this.editStore("yearsAndMonths", yearsAndMonths)
  95. })
  96. .catch(error => {
  97. console.warn(error)
  98. this.editStore("yearsAndMonths", undefined)
  99. });
  100. }
  101. /**
  102. * Triggered by the store whenever any store data changes. Sets us the store when yearsAndMonths data
  103. * has been set following the fetch statement
  104. *
  105. * @instance
  106. * @memberof Dashboard.YearsController
  107. **/
  108. storeUpdated(prop, storeId) {
  109. if (prop === "yearsAndMonths" && storeId === this.storeIdValue) {
  110. this.editStore("years", this.store("yearsAndMonths").map(data => data.year))
  111. this.editStore("yearSelected", this.store("years")[this.store("years").length - 1])
  112. this.editStore(
  113. "months", this.store("yearsAndMonths").slice(-1).map(data => data.month_numbers).flat()
  114. )
  115. this.editStore("monthSelected", this.store("months")[this.store("months").length - 1])
  116. this.statusValue = "loaded"
  117. }
  118. }
  119. /**
  120. * Unsubscribe from the store
  121. *
  122. * @instance
  123. * @memberof Dashboard.YearsController
  124. **/
  125. disconnect() {
  126. this.statusValue = "loading"
  127. this.unsubscribe()
  128. }
  129. }