All files / src/app/components/timetrack/date-picker date-picker.component.ts

97.4% Statements 75/77
87.5% Branches 21/24
100% Functions 11/11
97.22% Lines 70/72

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 1642x 2x 2x 2x 2x 2x                               2x 7x 7x         7x                   7x 7x 7x 7x   7x 7x 7x   7x   7x   7x           2x 2x 2x       1x 1x   1x 1x 1x   1x 1x                           1x 1x 1x 1x   1x 1x     2x   2x       7x 7x       1x                 2x 2x       4x 4x 4x 4x 4x         4x     4x     4x   4x 4x 4x 124x 100x 124x 124x 16x 16x 16x 16x 16x     4x 4x 2x 4x   4x       1x 1x      
import { CommonModule } from "@angular/common";
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { ActivatedRoute, Router, RouterModule } from "@angular/router";
import { TranslateModule, TranslateService } from "@ngx-translate/core";
import { isValidInteger } from "@shared/helper/utils";
import { map, Observable, Subject, takeUntil } from "rxjs";
import { DateI } from "../date";
import { DaySelector, WeekSelector } from "../timeunits";
 
@Component({
    selector: "app-date-picker",
    standalone: true,
    imports: [
        CommonModule,
        RouterModule,
        TranslateModule,
    ],
    templateUrl: "./date-picker.component.html",
    styleUrl: "./date-picker.component.css",
})
 
export class DatePickerComponent implements OnInit, OnDestroy {
  @Output() readonly selectedDate = new EventEmitter<DateI>();
  @Output() readonly monthChange = new EventEmitter<void>();
 
  @Input() setDays: number[] | null | undefined;
  
 
  private stop$ = new Subject<void>();
 
  /**
   * List of Days of the Current Month for display
   *
   * @type {WeekSelector[]}
   * @memberof DayselectComponent
   */
  month!: WeekSelector[];
 
  today = new Date();
  todayDate = this.today.getDate();
  todayMonth = this.today.getMonth();
  todayYear = this.today.getFullYear();
 
  selectedDay = 0;
  selectedMonth = 0;
  selectedYear = 0;
 
  hideWeekend = true;
 
  monthNames = [];
 
  constructor (private route: ActivatedRoute, private router: Router, public ts: TranslateService) {
  }
 
  ngOnInit (): void {
      let lastMonth: number;
      let lastYear: number;
      this.route.params.subscribe(params => {
          const { year, month, day } = params;
          if (!isValidInteger(year) || 
              !isValidInteger(month) ||
              !isValidInteger(day)) 
          {
              this.resetDate();
              return;
          }
          this.selectedYear = +year;
          this.selectedMonth = +month - 1;
          this.selectedDay = +day;
 
          const date = new Date(this.selectedYear, this.selectedMonth, this.selectedDay);
          Iif(
              date.getFullYear() !== this.selectedYear || 
              date.getMonth() !== this.selectedMonth || 
              date.getDate() !== this.selectedDay
          ) {
              this.router.navigate([
                  "timetrack",
                  date.getFullYear(),
                  date.getMonth() + 1,
                  date.getDate(),
              ]);
              return;
          }
 
          this.selectedDate.emit({year: this.selectedYear, month: this.selectedMonth + 1, day: this.selectedDay});
          this.updateCalender(this.selectedYear, this.selectedMonth);
          if(this.selectedYear !== lastYear || this.selectedMonth !== lastMonth)
              this.monthChange.emit();
 
          lastYear = this.selectedYear;
          lastMonth = this.selectedMonth;
      });
 
      this.ts.stream("months.full")
          .pipe(takeUntil(this.stop$))
          .subscribe(monthNames => this.monthNames = monthNames);
  }
 
  ngOnDestroy (): void {
      this.stop$.next();
      this.stop$.complete();
  }
 
  resetDate () {
      this.router.navigate([
          "timetrack",
          this.today.getFullYear(),
          this.today.getMonth() + 1,
          this.today.getDate(),
      ]);
  }
 
  toggleWeekend ($event: Event) {
      this.hideWeekend = !($event.target as HTMLInputElement).checked;
      this.updateCalender(this.selectedYear, this.selectedMonth);
  }
 
  getWeekNumber (date: Date): number {
      const target = new Date(date.valueOf());
      const dayNr = (date.getDay() + 6) % 7;
      target.setDate(target.getDate() + 4 - dayNr);
      const yearStart = new Date(target.getFullYear(), 0, 1);
      return Math.ceil(((((target.valueOf() - yearStart.valueOf()) / 1000) / 60 / 60 / 24) + 1) / 7);
  }
  
  updateCalender (year: number, month: number) {
      // Total Count of Days in given month
      const count = new Date(year, month + 1, 0).getDate();
 
      // First Weeknumber 
      let weeknumber = this.getWeekNumber(new Date(year, month, 1));
 
      //Get weekday in German writing (Sunday is 6)
      let weekday = new Date(year, month, 0).getDay();
 
      const weeks: WeekSelector[] = [];
      let days: DaySelector[] = [];
      for(let day = 1; day <= count; day++) {
          if(!(this.hideWeekend && weekday >= 5))
              days[weekday] = {date: day, weekday: weekday};
          weekday++;
          if(weekday >= 7) {
              weekday = 0;
              if(days.length)
                  weeks.push({days: days, weeknumber: weeknumber});
              days = [];
              weeknumber++;
          }
      }
      if(days.length) {
          if(!days[this.hideWeekend ? 4 : 6])
              days[this.hideWeekend ? 4 : 6] = {date: 0, weekday: 0};
          weeks.push({days: days, weeknumber: weeknumber});
      }
      this.month = weeks;
  }
 
  getWeekDays (): Observable<string[]> {
      const x = this.ts.get("days.short").pipe((map(days => days.slice(0, this.hideWeekend ? -2 : undefined))));
      return x;
  }
}