From dea632f67de944ef6e54d982f66d0e01f25b9584 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 30 Nov 2025 01:24:26 +0100 Subject: [PATCH] Fix signal immutability violations and cleanup unused code (#62) * Initial plan * fix: address PR review comments for signal immutability and cleanup Co-authored-by: THoguet <61246905+THoguet@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: THoguet <61246905+THoguet@users.noreply.github.com> --- src/app/components/user-input/user-input.html | 2 +- src/app/components/user-input/user-input.ts | 42 +++++++++---------- .../userInput/day-input/day-input.html | 2 +- .../userInput/day-input/day-input.spec.ts | 11 +++++ .../userInput/day-input/day-input.ts | 10 +++-- 5 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/app/components/user-input/user-input.html b/src/app/components/user-input/user-input.html index c2630a2..80fdb63 100644 --- a/src/app/components/user-input/user-input.html +++ b/src/app/components/user-input/user-input.html @@ -3,7 +3,7 @@
@for (day of daysOff; track day.id) {
- +
} diff --git a/src/app/components/user-input/user-input.ts b/src/app/components/user-input/user-input.ts index 8db3317..c3c72fc 100644 --- a/src/app/components/user-input/user-input.ts +++ b/src/app/components/user-input/user-input.ts @@ -1,27 +1,17 @@ -import { - Component, - OnInit, - OnDestroy, - computed, - inject, - ChangeDetectionStrategy, -} from '@angular/core'; +import { Component, computed, inject, ChangeDetectionStrategy } from '@angular/core'; import { MatInputModule } from '@angular/material/input'; -import { ReactiveFormsModule } from '@angular/forms'; import { UserInputService } from '../../services/user-input-service'; -import { Subject } from 'rxjs'; import { CalendarSettings } from '../calendar-settings/calendar-settings'; 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 { tooltipTypeMapping, DayType } from '../../services/calendar-service'; +import { tooltipTypeMapping, DayType, VacDay } from '../../services/calendar-service'; @Component({ selector: 'app-user-input', imports: [ MatInputModule, - ReactiveFormsModule, CalendarSettings, MatCard, MatCardContent, @@ -33,10 +23,8 @@ import { tooltipTypeMapping, DayType } from '../../services/calendar-service'; styleUrl: './user-input.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class UserInput implements OnInit, OnDestroy { +export class UserInput { private userInputService: UserInputService = inject(UserInputService); - public daysOff = this.userInputService.vacationNumberSignal(); - private destroy$ = new Subject(); protected remainingDays = computed(() => { const remaining = this.userInputService.remainingVacationDaysSignal(); @@ -60,23 +48,31 @@ export class UserInput implements OnInit, OnDestroy { protected hasRemainingDays = computed(() => this.remainingDays() > 0); - ngOnInit() {} - - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); + protected get daysOff() { + return this.userInputService.vacationNumberSignal(); } public addDay() { - this.daysOff.push(this.userInputService.createVacationDay()); + this.userInputService.vacationNumberSignal.update((days) => [ + ...days, + this.userInputService.createVacationDay(), + ]); } public removeFromList(index: number) { - this.daysOff.splice(index, 1); + 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() { // Trigger signal update by setting a new array reference - this.userInputService.vacationNumberSignal.set([...this.daysOff]); + this.userInputService.vacationNumberSignal.update((days) => [...days]); } } diff --git a/src/app/components/userInput/day-input/day-input.html b/src/app/components/userInput/day-input/day-input.html index 9f83199..51bdabb 100644 --- a/src/app/components/userInput/day-input/day-input.html +++ b/src/app/components/userInput/day-input/day-input.html @@ -10,7 +10,7 @@ /> - + @for (dayType of selectableDayTypes; track $index) { {{ tooltipTypeMapping[dayType] }} diff --git a/src/app/components/userInput/day-input/day-input.spec.ts b/src/app/components/userInput/day-input/day-input.spec.ts index c09c8a8..d0b1d71 100644 --- a/src/app/components/userInput/day-input/day-input.spec.ts +++ b/src/app/components/userInput/day-input/day-input.spec.ts @@ -1,18 +1,29 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { DayInput } from './day-input'; +import { SelectableDayType, VacDay } from '../../../services/calendar-service'; describe('DayInput', () => { let component: DayInput; let fixture: ComponentFixture; + const mockVacDay: VacDay = { + id: 'test-id', + type: SelectableDayType.CP, + numberOfDays: 5, + expiryDate: new Date('2025-12-31'), + }; + beforeEach(async () => { await TestBed.configureTestingModule({ imports: [DayInput], + providers: [provideAnimationsAsync()], }).compileComponents(); fixture = TestBed.createComponent(DayInput); component = fixture.componentInstance; + fixture.componentRef.setInput('day', mockVacDay); fixture.detectChanges(); }); diff --git a/src/app/components/userInput/day-input/day-input.ts b/src/app/components/userInput/day-input/day-input.ts index 3ec6f25..137d429 100644 --- a/src/app/components/userInput/day-input/day-input.ts +++ b/src/app/components/userInput/day-input/day-input.ts @@ -90,12 +90,14 @@ export class DayInput { onInput(event: Event) { const value = Number((event.target as HTMLInputElement).value); - this.day().numberOfDays = value; - this.dayChange.emit(this.day()); + this.dayChange.emit({ ...this.day(), numberOfDays: value }); + } + + onTypeChange(type: SelectableDayType) { + this.dayChange.emit({ ...this.day(), type }); } addEvent(event: MatDatepickerInputEvent) { - this.day().expiryDate = event.value!; - this.dayChange.emit(this.day()); + this.dayChange.emit({ ...this.day(), expiryDate: event.value! }); } }