/** * Copyright (c) HashiCorp, Inc. * SPDX-License-Identifier: MPL-2.0 */ import Component from '@glimmer/component'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; import { ARRAY_OF_MONTHS, parseAPITimestamp } from 'core/utils/date-formatters'; import { addYears, isSameYear, subYears } from 'date-fns'; /** * @module CalendarWidget * CalendarWidget component is used in the client counts dashboard to select a month/year to query the /activity endpoint. * The component returns an object with selected date info, example: { dateType: 'endDate', monthIdx: 0, monthName: 'January', year: 2022 } * * @example * ```js * * * @param {string} startTimestamp - ISO timestamp string of the calendar widget's start time, displays in dropdown trigger * @param {string} endTimestamp - ISO timestamp string for the calendar widget's end time, displays in dropdown trigger * @param {function} selectMonth - callback function from parent - fires when selecting a month or clicking "Current billing period" * /> * ``` */ export default class CalendarWidget extends Component { currentDate = new Date(); @tracked calendarDisplayDate = this.currentDate; // init to current date, updates when user clicks on calendar chevrons @tracked showCalendar = false; @tracked tooltipTarget = null; @tracked tooltipText = null; // both date getters return a date object get startDate() { return parseAPITimestamp(this.args.startTimestamp); } get endDate() { return parseAPITimestamp(this.args.endTimestamp); } get displayYear() { return this.calendarDisplayDate.getFullYear(); } get disableFutureYear() { return isSameYear(this.calendarDisplayDate, this.currentDate); } get disablePastYear() { // calendar widget should only go as far back as the passed in start time return isSameYear(this.calendarDisplayDate, this.startDate); } get widgetMonths() { const startYear = this.startDate.getFullYear(); const startMonthIdx = this.startDate.getMonth(); return ARRAY_OF_MONTHS.map((month, index) => { let readonly = false; // if widget is showing same year as @startTimestamp year, disable if month is before start month if (startYear === this.displayYear && index < startMonthIdx) { readonly = true; } // if widget showing current year, disable if month is later than current month if (this.displayYear === this.currentDate.getFullYear() && index > this.currentDate.getMonth()) { readonly = true; } return { index, year: this.displayYear, name: month, readonly, }; }); } @action addTooltip() { if (this.disablePastYear) { const previousYear = this.displayYear - 1; this.tooltipText = `${previousYear} is unavailable because it is before your start date. Change your start month to a date in ${previousYear} to see data for this year.`; this.tooltipTarget = '#previous-year'; } } @action removeTooltip() { this.tooltipTarget = null; } @action addYear() { this.calendarDisplayDate = addYears(this.calendarDisplayDate, 1); } @action subYear() { this.calendarDisplayDate = subYears(this.calendarDisplayDate, 1); } @action toggleShowCalendar() { this.showCalendar = !this.showCalendar; this.calendarDisplayDate = this.endDate; } @action handleDateShortcut(dropdown, { target }) { this.args.selectMonth({ dateType: target.name }); // send clicked shortcut to parent callback this.showCalendar = false; dropdown.close(); } @action selectMonth(month, dropdown) { const { index, year, name } = month; this.toggleShowCalendar(); this.args.selectMonth({ monthIdx: index, monthName: name, year, dateType: 'endDate' }); dropdown.close(); } }