|
|
@@ -0,0 +1,85 @@
|
|
|
+import {Component, ElementRef, Input, ViewChild} from '@angular/core';
|
|
|
+
|
|
|
+import {CalculatorService} from '../calculator.service';
|
|
|
+
|
|
|
+@Component({
|
|
|
+ selector: 'fc-date-range-slider',
|
|
|
+ templateUrl: './date-range-slider.component.html',
|
|
|
+})
|
|
|
+export class FcDateRangeSliderComponent {
|
|
|
+ @ViewChild('slider') sliderElement: ElementRef;
|
|
|
+ @Input() values: Array<string>;
|
|
|
+
|
|
|
+ constructor(public calcService: CalculatorService) {
|
|
|
+ this.calcService.dateCalendarSelects.subscribe(({date}) => {
|
|
|
+ this.sliderElement.nativeElement.value =
|
|
|
+ this.parseISOLocal(date).getTime();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ getMinInMillis() {
|
|
|
+ return this.parseISOLocal(this.getFirstDate()).getTime();
|
|
|
+ }
|
|
|
+
|
|
|
+ getMaxInMillis() {
|
|
|
+ return this.parseISOLocal(this.getLastDate()).getTime();
|
|
|
+ }
|
|
|
+
|
|
|
+ getFirstDate() {
|
|
|
+ return this.values?.[0] ?? '2000-01-01';
|
|
|
+ }
|
|
|
+
|
|
|
+ getLastDate() {
|
|
|
+ return this.values?.slice(-1)?.pop() ?? '3000-01-01';
|
|
|
+ }
|
|
|
+
|
|
|
+ // Inspired by https://stackoverflow.com/questions/8584902/get-the-closest-number-out-of-an-array
|
|
|
+ pickNearestDate(selected) {
|
|
|
+ selected = selected.target.value;
|
|
|
+ const nearestDate = this.values
|
|
|
+ .map((val) => this.parseISOLocal(val).getTime())
|
|
|
+ .reduce((prev, curr) => {
|
|
|
+ return Math.abs(curr - selected) < Math.abs(prev - selected)
|
|
|
+ ? curr
|
|
|
+ : prev;
|
|
|
+ });
|
|
|
+ this.calcService.dateRangeSelects.next({
|
|
|
+ date: this.dateToISOLocal(nearestDate),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Format date as YYYY-MM-DD
|
|
|
+ // Inspired by https://stackoverflow.com/questions/58153053/how-can-i-create-a-slider-that-would-display-date-and-is-there-a-way-to-make-ma
|
|
|
+ private dateToISOLocal(dateInMillis: number) {
|
|
|
+ const date = new Date(dateInMillis);
|
|
|
+ const form = (n) => ('0' + n).slice(-2);
|
|
|
+ return (
|
|
|
+ date.getFullYear() +
|
|
|
+ '-' +
|
|
|
+ form(date.getMonth() + 1) +
|
|
|
+ '-' +
|
|
|
+ form(date.getDate()) +
|
|
|
+ 'T' +
|
|
|
+ form(date.getHours()) +
|
|
|
+ ':' +
|
|
|
+ form(date.getMinutes()) +
|
|
|
+ ':' +
|
|
|
+ form(date.getSeconds())
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Parse date in YYYY-MM-DD format as local date
|
|
|
+ // Inspired by https://stackoverflow.com/questions/58153053/how-can-i-create-a-slider-that-would-display-date-and-is-there-a-way-to-make-ma
|
|
|
+ private parseISOLocal(s: string) {
|
|
|
+ const [y, m, d] = s.split('T')[0].split('-');
|
|
|
+ const [hh, mm, ss] = s.split('T')[1]?.split(':') ?? [0, 0, 0];
|
|
|
+ return new Date(
|
|
|
+ Number(y),
|
|
|
+ Number(m) - 1,
|
|
|
+ Number(d),
|
|
|
+ Number(hh),
|
|
|
+ Number(mm),
|
|
|
+ Number(ss)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|