import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewContainerRef, OnDestroy, AfterViewInit, } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; // moment import moment from 'moment'; // services import { CalendarDateTimePickerService } from './services/calendar-datetime-picker.service'; // components import { CaCustomDateTimePickersDateCalendarsComponent } from './components/ca-custom-datetime-pickers-date-calendars/ca-custom-datetime-pickers-date-calendars.component'; // constants import { CustomDatetimePickersConstants } from './utils/constants/custom-datetime-pickers.constants'; // models import { ICaInput } from '../ca-input/config/ca-input.config'; import { ScrollType } from './models/scroll-type.model'; // enums import { InputConfigNameStringEnum } from '../ca-input/enums/input-config-name-string.enum'; import { CalendarTypeStringEnum } from './enums/calendar-type-string.enum'; import { CalendarListPreviewStringEnum } from './enums/calendar-list-preview-string.enum'; import { CalendarScrollTypeStringEnum } from './enums/calendar-scroll-type-string.enum'; @Component({ selector: 'ca-custom-datetime-pickers-test', templateUrl: './ca-custom-datetime-pickers-test.component.html', styleUrls: ['./ca-custom-datetime-pickers-test.component.scss'], imports: [ CommonModule, FormsModule, CaCustomDateTimePickersDateCalendarsComponent, ] }) export class CaCustomDatetimePickersComponent implements OnInit, OnDestroy, AfterViewInit { @Input() dateTime!: Date; @ViewChild('ref', { read: ViewContainerRef }) ref!: ViewContainerRef; public _inputConfig!: ICaInput; @Input() set inputConfig(config: ICaInput) { this._inputConfig = config; if ( this._inputConfig.name === InputConfigNameStringEnum.DATE_PICKER_BANK_CARD ) this.listPreview = CalendarListPreviewStringEnum.MONTH_LIST; if (this._inputConfig.minutesGapFive) this.timeMinutes = CustomDatetimePickersConstants.timeMinutesGapFive; else this.timeMinutes = CustomDatetimePickersConstants.timeMinutes; } @Output() closePopover: EventEmitter = new EventEmitter(); @ViewChild(CaCustomDateTimePickersDateCalendarsComponent) dateCalendar!: CaCustomDateTimePickersDateCalendarsComponent; @ViewChild('pmAmScroll') pmAmScroll!: ElementRef; @ViewChild('minutesScroll') minutesScroll!: ElementRef; @ViewChild('hourScroll') hourScroll!: ElementRef; public selectedDateTime!: string; public calendarMainType!: string; public outputType!: (string | number)[]; public currentYear: number = new Date().getFullYear(); public currentMonth: number = new Date().getMonth(); public currentDay: number = new Date().getDate(); public listPreview: string = CalendarListPreviewStringEnum.FULL_LIST; public timeMinutes!: string[]; public monthArray: number[] = new Array(12) .fill(0) .map((_, indx) => indx + 1); public monthDayList: number[] = new Array(31) .fill(0) .map((_, indx) => indx + 1); public yearsList: (string | number)[] = new Array(100) .fill(0) .map((_, idx) => (idx < 10 ? '0' + idx : idx)); public scrollTimer!: ReturnType | number; public hoveredItem!: string | null; public isInputFocus!: boolean; public monthNames: string[] = CustomDatetimePickersConstants.monthNames; public hourTimes: number[] = CustomDatetimePickersConstants.hourTimes; public scrollTypes: ScrollType = CustomDatetimePickersConstants.defaultScrollTypes; public selectedTime: string = CustomDatetimePickersConstants.defaultSelectedTime; public timeOfDay: string[] = CustomDatetimePickersConstants.timeOfDay; public previousRangeSide!: boolean; constructor(private calendarService: CalendarDateTimePickerService) {} @Input() set calendarType(calendarType: string) { this.calendarMainType = calendarType; if (calendarType === CalendarTypeStringEnum.TIME) this.outputType = CustomDatetimePickersConstants.defaultOutputTypeTime; else this.outputType = CustomDatetimePickersConstants.defaultOutputTypeDate; } @Input() set placeholder(placeholder: string) { this.selectedDateTime = placeholder; } ngOnInit(): void { this.initDateChangedListener(); } ngAfterViewInit(): void { this.setTimeValue(); this.changeOpened(); } public initDateChangedListener(): void { this.calendarService.dateChanged.subscribe((date) => { if (this.calendarMainType !== CalendarTypeStringEnum.TIME) { this.outputType[0] = date[0]; this.outputType[2] = date[1]; this.outputType[4] = date[2]; this.selectedDateTime = this.createStringFromOutput(); } }); } public setTimeValue() { const dateInputArray = moment(this.dateTime) .format('H/mm/A') .split('/'); setTimeout(() => { this.scrollTypes.hourScroll = this.hourTimes.indexOf( parseInt(dateInputArray[0]) ); this.scrollTypes.minutesScroll = this.timeMinutes.indexOf( dateInputArray[1] ); this.scrollTypes.pmAmScroll = dateInputArray[2] === 'AM' ? 0 : 1; }); } public setListPreview(value: string): void { this.listPreview = value; } public inputInFocus(): void { this.isInputFocus = true; } public inputBlur(): void { this.isInputFocus = false; } public changeOpened(): void { // this.isInputFocus = e; // if (e) { if (this.calendarMainType === CalendarTypeStringEnum.TIME) { setTimeout(() => { this.hourScroll.nativeElement.scrollTop = this.scrollTypes.hourScroll * 22; this.minutesScroll.nativeElement.scrollTop = this.scrollTypes.minutesScroll * 22; this.pmAmScroll.nativeElement.scrollTop = this.scrollTypes.pmAmScroll * 22; }); } else { let test = `${ this.dateTime.getMonth() + 1 }/${this.dateTime.getDate()}/${this.dateTime.getFullYear()}`; this.calendarService.scrollToDate.next( `${ this.dateTime.getMonth() + 1 }/${this.dateTime.getDate()}/${this.dateTime.getFullYear()}` ); } } public setTime(): void { this.outputType[0] = this.hourTimes[this.scrollTypes.hourScroll]; this.outputType[2] = this.timeMinutes[this.scrollTypes.minutesScroll]; this.outputType[4] = this.timeOfDay[this.scrollTypes.pmAmScroll]; this.selectedDateTime = this.createStringFromOutput(); let currentDate = moment().format('MM/DD/YYYY'); this.calendarService.dateChanged.next( new Date(currentDate + ' ' + this.selectedDateTime) ); this.closePopover.emit(); } public setDefaultTime(): void { let currentDate = moment().format('MM/DD/YYYY'); this.calendarService.dateChanged.next(new Date(currentDate + ' 08:00')); this.closePopover.emit(); } public closePopup(): void { this.closePopover.emit(); } public createStringFromOutput(): string { return this.outputType.join(''); } public onScroll( event: Event, type: keyof ScrollType, index: number | null = null ): void { const scrolFromTop = Math.floor( (event.target as HTMLElement).scrollTop ); const scrollIndex = index === null ? Math.floor(scrolFromTop / 22) : index; const scrollRemaining = scrolFromTop % 22; clearInterval(this.scrollTimer); this.scrollTimer = setTimeout(() => { if (scrollRemaining < 11 && index === null) { (event.target as HTMLElement).scrollTop = scrollIndex * 22; this.scrollTypes[type] = scrollIndex; } else if (index !== null) { (( (event.target).parentNode )).scrollTop = scrollIndex * 22; this.scrollTypes[type] = scrollIndex; } else { (event.target as HTMLElement).scrollTop = (scrollIndex + 1) * 22; this.scrollTypes[type] = scrollIndex + 1; } this.checkForScrolledType(type); }, 200); } public checkForScrolledType(type: string): void { if (type === CalendarScrollTypeStringEnum.HOURS_SCROLL) { if (this.scrollTypes[type] >= 12) { this.pmAmScroll.nativeElement.scrollTop = 22; this.scrollTypes.pmAmScroll = 1; } else { this.pmAmScroll.nativeElement.scrollTop = 0; this.scrollTypes.pmAmScroll = 0; } } if (type === CalendarScrollTypeStringEnum.PM_AM_SCROLL) { if (this.scrollTypes[type] === 0) { if (this.scrollTypes.hourScroll >= 12) { this.hourScroll.nativeElement.scrollTop = (this.scrollTypes.hourScroll - 12) * 22; this.scrollTypes.hourScroll = Math.floor( this.scrollTypes.hourScroll - 12 ); } } else { if (this.scrollTypes.hourScroll < 12) { this.hourScroll.nativeElement.scrollTop = (this.scrollTypes.hourScroll + 12) * 22; this.scrollTypes.hourScroll = Math.floor( this.scrollTypes.hourScroll + 12 ); } } } this.selectedTime = `${this.hourTimes[this.scrollTypes.hourScroll]}:${ this.timeMinutes[this.scrollTypes.minutesScroll] } ${this.timeOfDay[this.scrollTypes.pmAmScroll]}`; } ngOnDestroy(): void { this.listPreview = CalendarListPreviewStringEnum.FULL_LIST; } }