feat: enhance loading spinner with progress indication and add warnin… (#49)

* feat: enhance loading spinner with progress indication and add warning for unplaced vacation days

* Update src/app/services/calendar-service.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/app/components/calendar-year/calendar-year.scss

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/app/components/user-input/user-input.html

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix setTimeout async anti-pattern in calendar-year component (#50)

* Initial plan

* fix: replace setTimeout async anti-pattern with queueMicrotask and void

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>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2025-11-18 00:45:05 +01:00
1 parent 2d5cccff0c
commit 3272622abf
8 files changed
+157 -37

No files matched your search

@@ -2,7 +2,10 @@
@if (isLoading()) {
<div class="loading-overlay">
<div class="loading-spinner">
<mat-spinner></mat-spinner>
<div class="spinner-container">
<mat-spinner [mode]="'determinate'" [value]="loadingProgress()"></mat-spinner>
<div class="spinner-text">{{ loadingProgress() }}%</div>
</div>
<p>Calcul en cours...</p>
</div>
</div>
@@ -51,25 +51,32 @@
}
}
.spinner-container {
position: relative;
display: inline-block;
::ng-deep .mat-mdc-progress-spinner {
// Override Material spinner size
width: 100px;
height: 100px;
}
.spinner-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
font-weight: bold;
color: #333;
pointer-events: none;
@media (prefers-color-scheme: dark) {
color: #ddd;
}
}
}
.card {
margin: 16px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:root {
@include mat.progress-spinner-overrides(
(
size: 0.5rem,
active-indicator-width: 0.25rem,
)
);
}
@@ -21,6 +21,7 @@ export class CalendarYear {
private calendarSettingsService = inject(CalendarSettingsService);
protected isLoading = signal(true);
protected loadingProgress = signal(0);
// Use DateCacheService instead of creating Date objects
private get currentMonth() {
@@ -39,18 +40,26 @@ export class CalendarYear {
console.log('Samedi Malin setting:', c);
console.log('Optimizing vacations with data:', vacationData);
this.isLoading.set(true);
// Simulate server-side calculation with a small delay
setTimeout(() => {
if (this.selectedDates) {
// Create a copy to avoid mutating the original signal data
this.selectedDates.optimizeVacations(
{ ...vacationData },
this.calendarSettingsService,
this.calendarService,
);
}
this.isLoading.set(false);
}, 1);
this.loadingProgress.set(0);
// Defer execution to allow UI to update
queueMicrotask(() => {
void (async () => {
if (this.selectedDates) {
// Create a copy to avoid mutating the original signal data
const remainingDays = await this.selectedDates.optimizeVacations(
{ ...vacationData },
this.calendarSettingsService,
this.calendarService,
(progress: number) => {
this.loadingProgress.set(progress);
},
);
// Update the remaining vacation days signal
this.userInput.remainingVacationDaysSignal.set(remainingDays);
}
this.isLoading.set(false);
})();
});
});
}