import { Component, Output, ViewChild, EventEmitter, Input, ElementRef, HostListener } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { NgbModal, NgbModalRef, NgbDateStruct, NgbCalendar, NgbDateAdapter } from "@ng-bootstrap/ng-bootstrap"; import { NgbDateNativeAdapter } from '@farmmaps/common'; const equals = (one: NgbDateStruct, two: NgbDateStruct) => one && two && two.year === one.year && two.month === one.month && two.day === one.day; const before = (one: NgbDateStruct, two: NgbDateStruct) => !one || !two ? false : one.year === two.year ? one.month === two.month ? one.day === two.day ? false : one.day < two.day : one.month < two.month : one.year < two.year; const after = (one: NgbDateStruct, two: NgbDateStruct) => !one || !two ? false : one.year === two.year ? one.month === two.month ? one.day === two.day ? false : one.day > two.day : one.month > two.month : one.year > two.year; @Component({ selector: 'fm-map-select-period-modal', templateUrl: 'select-period-modal.component.html', styleUrls: ['select-period-modal.component.scss'] }) export class SelectPeriodModalComponent { private modalName = 'selectPeriodModal'; private modalRef: NgbModalRef; private dateAdapter = new NgbDateNativeAdapter(); hoveredDate: NgbDateStruct; fromDate: NgbDateStruct; toDate: NgbDateStruct; @ViewChild('content', { static: true }) _templateModal:ElementRef; @Input() set modalState(_modalState:any) { if(_modalState == this.modalName) { this.openModal() } else if(this.modalRef) { this.closeModal(); } } @Input() set startDate(_modalState: Date) { this.fromDate = this.dateAdapter.fromModel(_modalState); } @Input() set endDate(_modalState: Date) { const d = new Date(_modalState); d.setDate(d.getDate() - 1); this.toDate = this.dateAdapter.fromModel(d); } @Output() onCloseModal = new EventEmitter(); @Output() onSelect = new EventEmitter<{ startDate: Date, endDate: Date }>(); constructor(private modalService: NgbModal, private calendar: NgbCalendar) { } openModal() { //Timeout trick to avoid ExpressionChangedAfterItHasBeenCheckedError setTimeout(() => this.modalRef = this.modalService.open(this._templateModal, { backdrop: 'static', keyboard: false})); } closeModal() { this.modalRef.close(); } ngOnInit(): void { } onDateChange(date: NgbDateStruct) { if (!this.fromDate && !this.toDate) { this.fromDate = date; } else if (this.fromDate && !this.toDate && after(date, this.fromDate)) { this.toDate = date; } else { this.toDate = null; this.fromDate = date; } } handleSelect(event:MouseEvent) { event.preventDefault(); if (this.fromDate && this.toDate && before(this.fromDate, this.toDate)) { const endDate = new Date(this.dateAdapter.toModel(this.toDate)); endDate.setDate(endDate.getDate() + 1); this.onSelect.emit({startDate:this.dateAdapter.toModel(this.fromDate),endDate:endDate}) } } isHovered = date => this.fromDate && !this.toDate && this.hoveredDate && after(date, this.fromDate) && before(date, this.hoveredDate); isInside = date => after(date, this.fromDate) && before(date, this.toDate); isFrom = date => equals(date, this.fromDate); isTo = date => equals(date, this.toDate); }