controllers/dashboard/months_controller.js

  1. import { Controller } from "@hotwired/stimulus"
  2. import { subscription } from "~/javascripts/store/mixins/subscription"
  3. const monthMapper = {
  4. 1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun", 7: "Jul", 8: "Aug", 9: "Sep", 10: "Oct",
  5. 11: "Nov", 12: "Dec"
  6. }
  7. /**
  8. * @class Dashboard.MonthsController
  9. * @classdesc Stimulus controller that handles the months buttons data and interaction.
  10. * @extends Controller
  11. **/
  12. export default class extends Controller {
  13. static targets = [ "buttonGroup", "button" ]
  14. static values = {
  15. function: String,
  16. storeId: String,
  17. yearSelected: Number
  18. }
  19. /**
  20. * Subscribe to the store.
  21. *
  22. * @instance
  23. * @memberof Dashboard.MonthsController
  24. **/
  25. connect() {
  26. subscription(this)
  27. this.subscribe()
  28. this.reconnect()
  29. }
  30. /**
  31. * Handles a repeated Turbo visit to the dashboard page.
  32. *
  33. * @instance
  34. * @memberof Dashboard.MonthsController
  35. **/
  36. reconnect() {
  37. if (this.store("selectedDataVizData")) {
  38. this.storeUpdated("monthSelected", this.storeIdValue)
  39. }
  40. }
  41. /**
  42. * Triggered when a year is set. Uses a document fragment to fully create the
  43. * months buttons before removing the load button and adding all the new months buttons. The last
  44. * button is set as selected
  45. *
  46. * @instance
  47. * @memberof Dashboard.MonthsController
  48. **/
  49. yearSelectedValueChanged() {
  50. if (this.yearSelectedValue !== 0) {
  51. const yearAndMonths = this.store("yearsAndMonths").find(data => data.year === this.yearSelectedValue)
  52. let fragment = document.createDocumentFragment()
  53. yearAndMonths.month_numbers.forEach(monthNumber => {
  54. const buttonClone = this.buttonTarget.cloneNode(false)
  55. const button = fragment.appendChild(buttonClone)
  56. button.innerHTML = monthMapper[monthNumber]
  57. });
  58. this.buttonTargets.forEach(buttonTarget => buttonTarget.remove())
  59. this.buttonGroupTarget.appendChild(fragment)
  60. this.buttonTargets.forEach(buttonTarget => buttonTarget.classList.remove("selected"))
  61. this.buttonTargets[this.buttonTargets.length - 1].classList.add("selected")
  62. }
  63. }
  64. /**
  65. * Ignores month if already clicked. Set the month clicked as selected in the store and gives the class
  66. * selected to the clicked month.
  67. *
  68. * @instance
  69. * @memberof Dashboard.MonthsController
  70. **/
  71. monthClicked(event) {
  72. if (this.store("monthSelected") === parseInt(event.target.innerHTML)) return
  73. this.editStore(
  74. "monthSelected",
  75. parseInt(Object.keys(monthMapper).find(key => monthMapper[key] === event.target.innerHTML))
  76. )
  77. this.buttonTargets.forEach(buttonTarget => buttonTarget.classList.remove("selected"))
  78. event.target.classList.add("selected")
  79. }
  80. /**
  81. * Fetch all of the data for the selected month. If the data for the month is already present
  82. * then it does not fetch again.
  83. *
  84. * @instance
  85. * @memberof Dashboard.MonthsController
  86. **/
  87. fetchDataVizData() {
  88. const year = this.store("yearSelected")
  89. const month =this.store("monthSelected")
  90. const data = this.store("dataVizData")[`${year}${month}`]
  91. if (data) {
  92. this.editStore("selectedDataVizData", data)
  93. } else {
  94. this.editStore("fetchingDataVizData", true)
  95. fetch(`/.netlify/functions/supabase-get-api?year=${year}&month=${month}`, {
  96. headers: { "Function-Name": this.functionValue }
  97. })
  98. .then(responseCheck => {
  99. if (!responseCheck.ok) { throw Error(responseCheck.status); }
  100. return responseCheck;
  101. })
  102. .then(res => res.json())
  103. .then(fetchedData => {
  104. this.editStore("fetchingDataVizData", false)
  105. let dataToUpdate = this.store("dataVizData")
  106. dataToUpdate[`${year}${month}`] = fetchedData
  107. this.editStore("dataVizData", dataToUpdate)
  108. this.editStore("selectedDataVizData", this.store("dataVizData")[`${year}${month}`])
  109. })
  110. .catch(error => {
  111. console.warn(error)
  112. this.editStore("fetchingDataVizData", false)
  113. });
  114. }
  115. }
  116. /**
  117. * Triggered by the store whenever any store data changes. Fetches the relevant data when a month is
  118. * selected
  119. *
  120. * @instance
  121. * @memberof Dashboard.MonthsController
  122. **/
  123. storeUpdated(prop, storeId) {
  124. this.yearSelectedValue = this.store("yearSelected")
  125. if (prop === "monthSelected" && storeId === this.storeIdValue) this.fetchDataVizData()
  126. }
  127. /**
  128. * Unsubscribe from the store
  129. *
  130. * @instance
  131. * @memberof Dashboard.MonthsController
  132. **/
  133. disconnect() {
  134. this.yearSelectedValue = ""
  135. this.unsubscribe()
  136. }
  137. }