import { Component, computed, inject, ChangeDetectionStrategy } from '@angular/core'; import { MatInputModule } from '@angular/material/input'; import { UserInputService } from '../../services/user-input-service'; import { RulesPanel } from '../rules-panel/rules-panel'; import { MatCard, MatCardContent } from '@angular/material/card'; import { MatIcon } from '@angular/material/icon'; import { DayInput } from '../userInput/day-input/day-input'; import { MatButtonModule } from '@angular/material/button'; import { VacDay } from '../../services/calendar-service'; import { TranslationService } from '../../services/translation-service'; @Component({ selector: 'app-user-input', imports: [ MatInputModule, RulesPanel, MatCard, MatCardContent, MatIcon, MatButtonModule, DayInput, ], templateUrl: './user-input.html', styleUrl: './user-input.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class UserInput { private userInputService: UserInputService = inject(UserInputService); protected readonly translationService = inject(TranslationService); get tr() { return this.translationService.tr; } protected remainingDays = computed(() => { const remaining = this.userInputService.remainingVacationDaysSignal(); return remaining.reduce((acc, day) => acc + day.numberOfDays, 0); }); protected remainingDaysDetails = computed(() => { const remaining = this.userInputService.remainingVacationDaysSignal(); return remaining .filter((day) => day.numberOfDays > 0) .map((day) => { const typeName = this.translationService.getDayTypeLabel(day.type); const expiryDate = day.expiryDate.toLocaleDateString( this.translationService.locale(), { day: 'numeric', month: 'short', year: 'numeric', }, ); const expiresLabel = this.tr().userInput.expires; const classification = day.classification ? this.getClassificationLabel(day.classification) : ''; const reason = day.classification ? this.getReasonLabel(day.classification) : ''; const explanation = classification ? `${classification}: ${reason}; ` : ''; return `${day.numberOfDays} ${typeName} (${explanation}${expiresLabel} ${expiryDate})`; }); }); private getClassificationLabel(classification: NonNullable): string { const labels = this.tr().userInput.remainingClassification; if (classification === 'unavoidable-expiry') return labels.unavoidableExpiry; if (classification === 'at-risk') return labels.atRisk; return labels.deferred; } private getReasonLabel(classification: NonNullable): string { const labels = this.tr().userInput.remainingReason; if (classification === 'unavoidable-expiry') return labels.unavoidableExpiry; if (classification === 'at-risk') return labels.atRisk; return labels.deferred; } protected hasRemainingDays = computed(() => this.remainingDays() > 0); protected get daysOff() { return this.userInputService.vacationNumberSignal(); } public addDay() { this.userInputService.vacationNumberSignal.update((days) => [ ...days, this.userInputService.createVacationDay(), ]); } public removeFromList(index: number) { this.userInputService.vacationNumberSignal.update((days) => days.filter((_, i) => i !== index), ); } public updateDay(index: number, updatedDay: VacDay) { this.userInputService.vacationNumberSignal.update((days) => days.map((day, i) => (i === index ? updatedDay : day)), ); } public triggerComputation() { this.userInputService.requestComputation(); } }