import { Controller } from "@hotwired/stimulus"
import { subscription } from "~/javascripts/store/mixins/subscription"
/**
* @class Dashboard.YearsController
* @classdesc Stimulus controller that fetches the data to populate the years and months buttons.
* @extends Controller
**/
export default class extends Controller {
static targets = [ "buttonGroup", "button" ]
static values = {
storeId: String,
function: String,
status: String
}
/**
* Subscribe to the store. Setup dataVizData and then fetch years and months data
*
* @instance
* @memberof Dashboard.YearsController
**/
connect() {
subscription(this)
this.subscribe()
if (!this.store("dataVizData")) this.editStore("dataVizData", {})
if (!this.store("yearsAndMonths")) this.yearsAndMonths()
this.reconnect()
}
/**
* Handles a repeated Turbo visit to the dashboard page.
*
* @instance
* @memberof Dashboard.YearsController
**/
reconnect() {
if (this.store("selectedDataVizData")) {
this.storeUpdated("yearsAndMonths", this.storeIdValue)
}
}
/**
* Triggered when the years and months data is loaded. Uses a document fragment to fully create the
* years buttons before removing the load button and adding all the new years buttons. The last button
* is set as selected
*
* @instance
* @memberof Dashboard.YearsController
**/
statusValueChanged() {
if (this.statusValue === "loaded") {
let fragment = document.createDocumentFragment()
this.store("years").forEach(year => {
const buttonClone = this.buttonTarget.cloneNode(false)
const button = fragment.appendChild(buttonClone)
button.innerHTML = year
});
this.buttonTarget.remove()
this.buttonGroupTarget.appendChild(fragment)
this.buttonTargets[this.buttonTargets.length - 1].classList.add("selected")
}
}
/**
* Ignores year if already clicked. Set the months data for the selected year. Set the last month as
* selected in the store and gives the class selected to the clicked year.
*
* @instance
* @memberof Dashboard.YearsController
**/
yearClicked(event) {
if (this.store("yearSelected") === parseInt(event.target.innerHTML)) return
this.editStore("yearSelected", parseInt(event.target.innerHTML))
const yearAndMonths = this.store("yearsAndMonths").find(data => {
return data.year === this.store("yearSelected")
})
this.editStore("months", yearAndMonths.month_numbers)
this.editStore("monthSelected", this.store("months")[this.store("months").length - 1])
this.buttonTargets.forEach(buttonTarget => buttonTarget.classList.remove("selected"))
event.target.classList.add("selected")
}
/**
* Fetch the data for years and months.
*
* @instance
* @memberof Dashboard.YearsController
**/
yearsAndMonths() {
fetch("/.netlify/functions/supabase-get-functions", {
headers: { "Function-Name": this.functionValue }
})
.then(responseCheck => {
if (!responseCheck.ok) { throw Error(responseCheck.status); }
return responseCheck;
})
.then(res => res.json())
.then(yearsAndMonths => {
this.editStore("yearsAndMonths", yearsAndMonths)
})
.catch(error => {
console.warn(error)
this.editStore("yearsAndMonths", undefined)
});
}
/**
* Triggered by the store whenever any store data changes. Sets us the store when yearsAndMonths data
* has been set following the fetch statement
*
* @instance
* @memberof Dashboard.YearsController
**/
storeUpdated(prop, storeId) {
if (prop === "yearsAndMonths" && storeId === this.storeIdValue) {
this.editStore("years", this.store("yearsAndMonths").map(data => data.year))
this.editStore("yearSelected", this.store("years")[this.store("years").length - 1])
this.editStore(
"months", this.store("yearsAndMonths").slice(-1).map(data => data.month_numbers).flat()
)
this.editStore("monthSelected", this.store("months")[this.store("months").length - 1])
this.statusValue = "loaded"
}
}
/**
* Unsubscribe from the store
*
* @instance
* @memberof Dashboard.YearsController
**/
disconnect() {
this.statusValue = "loading"
this.unsubscribe()
}
}