Files
vac-optimizer/src/app/components/user-input/user-input.ts
T
nessar 609b3dece9 feat: enhance user input and rules panel components
- Updated dark-light mode button styles for improved responsiveness.
- Enhanced rules panel with additional buttons for moving rules up and down, and updated styles for better layout.
- Added active rule count display in the rules panel header.
- Improved user input component layout with section headings and updated button styles.
- Refactored day input component to use grid layout for better alignment and responsiveness.
- Added new translations for user input and rules panel features.
- Implemented tests for new functionality in rules panel and day input components.
- Added application routes test to ensure correct routing configuration.
2026-08-30 19:16:36 +02:00

107 lines
3.5 KiB
TypeScript

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<VacDay['classification']>): 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<VacDay['classification']>): 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();
}
}