diff --git a/src/app/app.ts b/src/app/app.ts
index c62efae..835574a 100644
--- a/src/app/app.ts
+++ b/src/app/app.ts
@@ -5,6 +5,7 @@ import { MatDivider } from '@angular/material/divider';
import { UserInput } from './components/user-input/user-input';
import { CalendarYear } from './components/calendar-year/calendar-year';
import { DarkLightModeButton } from './components/dark-light-mode-button/dark-light-mode-button';
+import { MatIcon } from '@angular/material/icon';
@Component({
selector: 'app-root',
@@ -15,6 +16,7 @@ import { DarkLightModeButton } from './components/dark-light-mode-button/dark-li
CalendarYear,
DarkLightModeButton,
DarkLightModeButton,
+ MatIcon,
],
templateUrl: './app.html',
styleUrl: './app.scss',
diff --git a/src/app/components/calendar-year/calendar-year.ts b/src/app/components/calendar-year/calendar-year.ts
index 676cbfd..ca8d3ae 100644
--- a/src/app/components/calendar-year/calendar-year.ts
+++ b/src/app/components/calendar-year/calendar-year.ts
@@ -24,7 +24,9 @@ export class CalendarYear {
effect(() => {
this.selectedDates = this.calendarService.getSelectedDatesForYear();
const vacationData = this.userInput.vacationNumberSignal();
- this.calendarSettingsService.samediMalin();
+ const c = this.calendarSettingsService.samediMalin();
+ 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(() => {
diff --git a/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.html b/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.html
index e9a4646..ee13da6 100644
--- a/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.html
+++ b/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.html
@@ -1,33 +1,29 @@
-@defer (hydrate on viewport) {
-
-
-
Calendar Settings
-
Configure your calendar settings here.
-
-
-
-
- Afficher les numéros de semaine
-
-
-
-
- Activer le Samedi Malin
-
-
-
-
+
+
+
Calendar Settings
+
Configure your calendar settings here.
-} @placeholder {
-
loading ...
-}
+
+
+
+ Afficher les numéros de semaine
+
+
+
+
+ Activer le Samedi Malin
+
+
+
+
+
diff --git a/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.ts b/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.ts
index e0e17ef..24255e5 100644
--- a/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.ts
+++ b/src/app/components/dialog/calendar-settings-dialog/calendar-settings-dialog.ts
@@ -4,6 +4,7 @@ import { MatCheckbox } from '@angular/material/checkbox';
import { MatDialogRef } from '@angular/material/dialog';
import { CalendarSettingsService } from '../../../services/calendar-settings-service';
import { MatSlideToggle } from '@angular/material/slide-toggle';
+import { CdkFixedSizeVirtualScroll } from '@angular/cdk/scrolling';
@Component({
selector: 'app-calendar-settings-dialog',
diff --git a/src/app/services/calendar-service.ts b/src/app/services/calendar-service.ts
index 37cfd20..361bb83 100644
--- a/src/app/services/calendar-service.ts
+++ b/src/app/services/calendar-service.ts
@@ -217,6 +217,7 @@ export class SelectedDate implements SelectedDateInterface {
isSelected(date: Date): boolean {
return (
+ this.type !== DayType.TODAY &&
this.range.start !== null &&
this.range.end !== null &&
date >= this.range.start &&
@@ -262,6 +263,9 @@ export class SelectedDates implements SelectedDateInterface {
_datesSelected: SelectedDate[] = [];
datesSelected: SelectedDate[] = [];
+ private minDate: Date | null = null;
+ private maxDate: Date | null = null;
+
update(): void {
this.datesSelected = this._datesSelected.slice();
this.grouping();
@@ -270,15 +274,38 @@ export class SelectedDates implements SelectedDateInterface {
push(selectedDate: SelectedDate) {
this._datesSelected.push(selectedDate);
this.datesSelected = this._datesSelected.slice();
+ this.updateMinMaxDates();
this.grouping();
}
+ private updateMinMaxDates(): void {
+ if (this._datesSelected.length === 0) {
+ this.minDate = null;
+ this.maxDate = null;
+ return;
+ }
+
+ this.minDate = this._datesSelected.reduce((min, date) => {
+ if (!date.range.start) return min;
+ if (!min) return date.range.start;
+ return date.range.start < min ? date.range.start : min;
+ }, this._datesSelected[0].range.start);
+
+ this.maxDate = this._datesSelected.reduce((max, date) => {
+ if (!date.range.end) return max;
+ if (!max) return date.range.end;
+ return date.range.end > max ? date.range.end : max;
+ }, this._datesSelected[0].range.end);
+ }
+
// make a "mother group" with type = null when two or more groups are adjacent or overlapping; keep the children groups
grouping(): void {
if (this._datesSelected.length <= 1) {
return;
}
+ const oneDayInMs = 24 * 60 * 60 * 1000;
+
// Sort dates by start date
const sorted = [...this._datesSelected].sort((a, b) => {
const aStart = a.range.start?.getTime() ?? 0;
@@ -289,25 +316,23 @@ export class SelectedDates implements SelectedDateInterface {
// Group adjacent or overlapping dates
const groups: SelectedDate[][] = [];
let currentGroup: SelectedDate[] = [sorted[0]];
+ let currentGroupMaxEnd = sorted[0].range.end?.getTime() ?? 0;
for (let i = 1; i < sorted.length; i++) {
const current = sorted[i];
- const previous = sorted[i - 1];
-
- const prevEnd = previous.range.end?.getTime() ?? 0;
const currStart = current.range.start?.getTime() ?? 0;
+ const currEnd = current.range.end?.getTime() ?? 0;
- // Check if dates are adjacent (next day) or overlapping
- const oneDayInMs = 24 * 60 * 60 * 1000;
- const isAdjacent = currStart - prevEnd <= oneDayInMs;
-
- if (isAdjacent) {
+ // Check if current date is adjacent or overlapping with the maximum end of the current group
+ if (currStart - currentGroupMaxEnd <= oneDayInMs) {
currentGroup.push(current);
+ currentGroupMaxEnd = Math.max(currentGroupMaxEnd, currEnd);
} else {
if (currentGroup.length > 1) {
groups.push(currentGroup);
}
currentGroup = [current];
+ currentGroupMaxEnd = Math.max(currentGroupMaxEnd, currEnd);
}
}
@@ -316,26 +341,19 @@ export class SelectedDates implements SelectedDateInterface {
groups.push(currentGroup);
}
- // Create mother groups and rebuild datesSelected
+ // Create mother groups and add to result
const result: SelectedDate[] = [...this._datesSelected];
for (const group of groups) {
- const groupStart = group.reduce((min, date) => {
- const start = date.range.start?.getTime() ?? 0;
- return min === 0 ? start : Math.min(min, start);
- }, 0);
+ const groupStart = Math.min(...group.map((d) => d.range.start?.getTime() ?? Infinity));
+ const groupEnd = Math.max(...group.map((d) => d.range.end?.getTime() ?? 0));
- const groupEnd = group.reduce((max, date) => {
- const end = date.range.end?.getTime() ?? 0;
- return Math.max(max, end);
- }, 0);
-
- const motherGroup = new SelectedDate(
- null,
- new DateRange
(new Date(groupStart), new Date(groupEnd)),
+ result.push(
+ new SelectedDate(
+ null,
+ new DateRange(new Date(groupStart), new Date(groupEnd)),
+ ),
);
-
- result.push(motherGroup);
}
this.datesSelected = result;
@@ -513,6 +531,9 @@ export class SelectedDates implements SelectedDateInterface {
}
samediMalin(vacationsNumber: VacationsNumber): void {
+ const now = new Date();
+ now.setHours(0, 0, 0, 0);
+
const samedi_ferie = this.datesSelected.filter(
(date) => date.type === DayType.CLOSED_DAY && date.range.start?.getDay() === 6,
);
@@ -549,15 +570,21 @@ export class SelectedDates implements SelectedDateInterface {
const oneDayAfter = new Date(sundayDate);
oneDayAfter.setDate(sundayDate.getDate() + 1);
- // Check if we can apply each strategy
+ // Check if we can apply each strategy (and not in the past)
const canApplyTwoBeforeStrategy =
- !this.isSelected(twoDaysBefore1) && !this.isSelected(twoDaysBefore2);
+ twoDaysBefore1 >= now &&
+ !this.isSelected(twoDaysBefore1) &&
+ !this.isSelected(twoDaysBefore2);
const canApplyTwoAfterStrategy =
- !this.isSelected(twoDaysAfter1) && !this.isSelected(twoDaysAfter2);
+ twoDaysAfter1 >= now &&
+ !this.isSelected(twoDaysAfter1) &&
+ !this.isSelected(twoDaysAfter2);
const canApplyMixedStrategy =
- !this.isSelected(oneDayBefore) && !this.isSelected(oneDayAfter);
+ oneDayBefore >= now &&
+ !this.isSelected(oneDayBefore) &&
+ !this.isSelected(oneDayAfter);
// Test all applicable strategies and choose the one with the best heuristic score
const strategies: { apply: () => void; heuristic: number }[] = [];