import { WeekDay } from '@angular/common' ; import { Injectable , OnDestroy } from '@angular/core' ; import { BehaviorSubject , combineLatest , Subscription } from 'rxjs' ; import { DateTimePickerService , ModeDirection } from '../date-time-picker.service' ; import { compareDays , dateRange , gridify } from '../date-time-picker.utils' ; @ Injectable ( ) export class DayViewService implements OnDestroy { grid$ = new BehaviorSubject < DayViewItem [ ] [ ] > ( [ [ ] ] ) ; focused$ = new BehaviorSubject < FocusedDayItem > ( null ) ; private _subscription : Subscription ; constructor ( private _datepicker ) { this . _subscription = combineLatest ( _datepicker . month$ , _datepicker . year$ , _datepicker . startOfWeek$ ) . subscribe ( ( [ month , year ] ) => this . createDayGrid ( month , year ) ) ; } ngOnDestroy ( ) { this . _subscription . unsubscribe ( ) ; } setFocus ( day , month , year ) { this . focused$ . next ( { day , month , year } ) ; this . _datepicker . setViewportMonth ( month ) ; this . _datepicker . setViewportYear ( year ) ; } private createDayGrid ( month , year ) { this . _datepicker . setHeader ( this . _datepicker . months [ month ] + ' ' + year ) ; const start = new Date ( year , month , 1 ) ; const end = new Date ( year , month + 1 , 0 ) ; const startOfWeek = Math . min ( WeekDay . Saturday , Math . max ( WeekDay . Sunday , this . _datepicker . startOfWeek$ . value ) ) ; while ( start . getDay ( ) !== startOfWeek ) { start . setDate ( start . getDate ( ) - 1 ) ; } end . setDate ( end . getDate ( ) + ( 6 - end . getDay ( ) ) ) ; const dates = dateRange ( start , end ) . map ( date => ( { day : date . getDate ( ) , month : date . getMonth ( ) , year : date . getFullYear ( ) , date , isToday : this . isToday ( date ) , isActive : this . isActive ( date ) , isCurrentMonth : date . getMonth ( ) === month } ) ) ; const items = gridify ( dates , 7 ) ; this . grid$ . next ( items ) ; if ( ( this . _datepicker . modeDirection === ModeDirection . None || this . _datepicker . modeDirection === ModeDirection . Descend ) && this . focused$ . value === null ) { const selectedDay = dates . find ( day => day . isCurrentMonth && day . isActive ) ; if ( selectedDay ) { this . setFocus ( selectedDay . day , selectedDay . month , selectedDay . year ) ; } else { const first = dates . find ( date => date . day === 1 ) ; this . setFocus ( first . day , first . month , first . year ) ; } } } param date private isToday ( date ) { return compareDays ( new Date ( ) , date ) ; } param date private isActive ( date ) { return this . _datepicker . selected$ . value ? compareDays ( this . _datepicker . selected$ . value , date ) : false ; } } export interface DayViewItem { day : number ; month : number ; year : number ; date : Date ; isToday : boolean ; isActive : boolean ; isCurrentMonth : boolean ; } export interface FocusedDayItem { day : number ; month : number ; year : number ; }