add calendar settings

This commit is contained in:
nessar committed 2025-11-01 03:15:30 +01:00
1 parent d8759eee29
commit d01c93c763
32 files changed
+1290 -1585

No files matched your search

@@ -2,6 +2,9 @@
<h3>{{ getMonthName() }} {{ year }}</h3>
<div>
<div class="row header">
@if (calendarSettingsService.showWeekNumbers()) {
<p class="day empty week-number"></p>
}
<p class="day">L</p>
<p class="day">M</p>
<p class="day">M</p>
@@ -12,16 +15,36 @@
</div>
<div class="cols">
@for (week of weeksInAMonth; track $index) {
<div class="row week">
@for (day of week; track $index) {
@if (day === null) {
<p class="day empty"></p>
} @else {
<p [class.past]="day < getNow()" [class.start]="selectedDates.isStart(day)" [class.end]="selectedDates.isEnd(day)" [class.selected]="selectedDates.isSelected(day)"
[class]="selectedDates.getClasses(day)" class="day number" [matTooltip]="selectedDates.getTooltip(day)" [matTooltipShowDelay]="500">{{ day.getDate() }}</p>
}
}
</div>
<div class="row week">
@if (calendarSettingsService.showWeekNumbers()) {
<p
class="day week-number"
[class.start]="$index === 0"
[class.end]="$index === weeksInAMonth.length - 1"
>
{{ getWeekNumber(week) }}
</p>
}
@for (day of week; track $index) {
@if (day === null) {
<p class="day empty"></p>
} @else {
<p
[class.past]="day < getNow()"
[class.start]="selectedDates.isStart(day)"
[class.end]="selectedDates.isEnd(day)"
[class.selected]="selectedDates.isSelected(day)"
[class]="selectedDates.getClasses(day)"
class="day number"
[matTooltip]="selectedDates.getTooltip(day)"
[matTooltipShowDelay]="500"
[matTooltipTouchGestures]="'on'"
>
{{ day.getDate() }}
</p>
}
}
</div>
}
</div>
</div>
@@ -103,3 +103,27 @@
.other {
background-color: var(--other-bg);
}
.row .week-number {
height: 30px;
font-weight: bold;
color: var(--week-number-color);
margin-right: 0.5rem;
background-color: var(--week-number-bg);
border-radius: 0;
margin-top: 0;
margin-bottom: 0;
}
.row .week-number:hover {
background-color: var(--week-number-bg-hover);
cursor: default;
}
.row .week-number.start {
border-radius: 30% 30% 0 0;
}
.row .week-number.end {
border-radius: 0 0 30% 30%;
}
@@ -1,6 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
import { CalendarService, Month, monthNames, SelectedDates } from '../../services/calendar-service';
import { MatTooltip } from '@angular/material/tooltip';
import { CalendarSettingsService } from '../../services/calendar-settings-service';
@Component({
selector: 'app-calendar-month',
@@ -9,6 +10,7 @@ import { MatTooltip } from '@angular/material/tooltip';
styleUrl: './calendar-month.scss',
})
export class CalendarMonth implements OnInit {
constructor(protected calendarSettingsService: CalendarSettingsService) {}
@Input({ required: true })
monthIndex!: number;
@@ -26,7 +28,6 @@ export class CalendarMonth implements OnInit {
weeksInAMonth: Month = [];
@Input({ required: true })
selectedDates!: SelectedDates;
@@ -34,6 +35,15 @@ export class CalendarMonth implements OnInit {
return monthNames[this.monthIndex];
}
getWeekNumber(week: (Date | null)[]): number | null {
for (const day of week) {
if (day) {
return CalendarService.getWeekNumber(day);
}
}
return null;
}
ngOnInit(): void {
this.weeksInAMonth = CalendarService.weeksInMonth(this.monthIndex, this.year);
}
@@ -0,0 +1,4 @@
<button matFab extended (click)="openDialog()">
<mat-icon>settings</mat-icon>
Calendar Settings
</button>
Whitespace-only changes.
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CalendarSettings } from './calendar-settings';
describe('CalendarSettings', () => {
let component: CalendarSettings;
let fixture: ComponentFixture<CalendarSettings>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CalendarSettings]
})
.compileComponents();
fixture = TestBed.createComponent(CalendarSettings);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,20 @@
import { Component } from '@angular/core';
import { MatButton, MatButtonModule } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { MatIcon, MatIconModule } from '@angular/material/icon';
import { CalendarSettingsDialog } from '../dialog/calendar-settings-dialog/calendar-settings-dialog';
import { MatDividerModule } from '@angular/material/divider';
@Component({
selector: 'app-calendar-settings',
imports: [MatButtonModule, MatDividerModule, MatIconModule],
templateUrl: './calendar-settings.html',
styleUrl: './calendar-settings.scss',
})
export class CalendarSettings {
constructor(private dialog: MatDialog) {}
openDialog() {
this.dialog.open(CalendarSettingsDialog);
}
}
@@ -1,10 +1,11 @@
import { Component, effect, signal } from '@angular/core';
import { UserInputService } from '../../services/user-input-service';
import { MatCard, MatCardContent } from '@angular/material/card';
import { CalendarMonth } from "../calendar-month/calendar-month";
import { CalendarMonth } from '../calendar-month/calendar-month';
import { CalendarService, SelectedDates } from '../../services/calendar-service';
import { CommonModule } from '@angular/common';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { CalendarSettingsService } from '../../services/calendar-settings-service';
@Component({
selector: 'app-calendar-year',
@@ -15,15 +16,24 @@ import { MatProgressSpinner } from '@angular/material/progress-spinner';
export class CalendarYear {
protected isLoading = signal(true);
constructor(private userInput: UserInputService, private calendarService: CalendarService) {
constructor(
private userInput: UserInputService,
private calendarService: CalendarService,
private calendarSettingsService: CalendarSettingsService,
) {
effect(() => {
this.selectedDates = this.calendarService.getSelectedDatesForYear();
const vacationData = this.userInput.vacationNumberSignal();
this.calendarSettingsService.samediMalin();
this.isLoading.set(true);
// Simulate server-side calculation with a small delay
setTimeout(() => {
if (this.selectedDates) {
this.selectedDates.optimizeVacations(vacationData);
// Create a copy to avoid mutating the original signal data
this.selectedDates.optimizeVacations(
{ ...vacationData },
this.calendarSettingsService,
);
}
this.isLoading.set(false);
}, 1);
@@ -38,5 +48,8 @@ export class CalendarYear {
}
// months starting from actual date
protected months: number[] = Array.from({ length: 12 }, (_, i) => (new Date().getMonth() + i) % 12);
protected months: number[] = Array.from(
{ length: 12 },
(_, i) => (new Date().getMonth() + i) % 12,
);
}
@@ -0,0 +1,33 @@
@defer (hydrate on viewport) {
<div class="container">
<div>
<h1>Calendar Settings</h1>
<p>Configure your calendar settings here.</p>
</div>
<div style="display: flex; flex-direction: column; gap: 1rem">
<div style="align-self: flex-start">
<mat-slide-toggle
id="showWeekNumbers"
name="showWeekNumbers"
[checked]="calendarSettingsService.showWeekNumbers()"
(change)="calendarSettingsService.showWeekNumbers.set($event.checked)"
>
Afficher les numéros de semaine
</mat-slide-toggle>
</div>
<div style="align-self: flex-start">
<mat-slide-toggle
id="samediMalin"
name="samediMalin"
[checked]="calendarSettingsService.samediMalin()"
(change)="calendarSettingsService.samediMalin.set($event.checked)"
>
Activer le Samedi Malin
</mat-slide-toggle>
</div>
</div>
<button mat-button (click)="closeDialog()">Fermer</button>
</div>
} @placeholder {
<p>loading ...</p>
}
@@ -0,0 +1,9 @@
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
flex-direction: column;
overflow: hidden;
margin: 16px;
}
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CalendarSettingsDialog } from './calendar-settings-dialog';
describe('CalendarSettingsDialog', () => {
let component: CalendarSettingsDialog;
let fixture: ComponentFixture<CalendarSettingsDialog>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CalendarSettingsDialog]
})
.compileComponents();
fixture = TestBed.createComponent(CalendarSettingsDialog);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,23 @@
import { Component } from '@angular/core';
import { MatButton } from '@angular/material/button';
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';
@Component({
selector: 'app-calendar-settings-dialog',
imports: [MatButton, MatSlideToggle],
templateUrl: './calendar-settings-dialog.html',
styleUrl: './calendar-settings-dialog.scss',
})
export class CalendarSettingsDialog {
constructor(
public dialogRef: MatDialogRef<CalendarSettingsDialog>,
protected calendarSettingsService: CalendarSettingsService,
) {}
closeDialog() {
this.dialogRef.close();
}
}
@@ -14,4 +14,5 @@
<input matInput type="number" max="365" min="0" formControlName="Others" />
</mat-form-field>
</form>
<app-calendar-settings></app-calendar-settings>
</div>
@@ -18,5 +18,4 @@
form {
display: flex;
flex-direction: column;
gap: 1rem;
}
+19 -11
View File
@@ -5,10 +5,18 @@ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angula
import { UserInputService } from '../../services/user-input-service';
import { VacationsNumber } from '../../services/calendar-service';
import { debounceTime, takeUntil, Subject } from 'rxjs';
import { CalendarSettings } from '../calendar-settings/calendar-settings';
@Component({
selector: 'app-user-input',
imports: [MatFormField, MatLabel, MatInputModule, ReactiveFormsModule],
imports: [
MatFormField,
MatLabel,
MatInputModule,
ReactiveFormsModule,
CalendarSettings,
CalendarSettings,
],
templateUrl: './user-input.html',
styleUrl: './user-input.scss',
})
@@ -17,11 +25,14 @@ export class UserInput implements OnInit, OnDestroy {
// Watch for signal changes and update form
effect(() => {
const vacationData = this.userInputService.vacationNumberSignal();
this.userInputForm.patchValue({
CP: vacationData.cp,
RTT: vacationData.rtt,
Others: vacationData.other,
}, { emitEvent: false });
this.userInputForm.patchValue(
{
CP: vacationData.cp,
RTT: vacationData.rtt,
Others: vacationData.other,
},
{ emitEvent: false },
);
});
}
@@ -35,10 +46,7 @@ export class UserInput implements OnInit, OnDestroy {
ngOnInit() {
this.userInputForm.valueChanges
.pipe(
debounceTime(1500),
takeUntil(this.destroy$)
)
.pipe(debounceTime(1500), takeUntil(this.destroy$))
.subscribe(() => this.submitForm());
}
@@ -54,7 +62,7 @@ export class UserInput implements OnInit, OnDestroy {
rtt: this.userInputForm.get('RTT')?.value || 0,
other: this.userInputForm.get('Others')?.value || 0,
};
this.userInputService.setVacationNumber(vacationData);
this.userInputService.vacationNumberSignal.set(vacationData);
}
}
}
@@ -0,0 +1 @@
<p>user-settings works!</p>
Whitespace-only changes.
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserSettings } from './user-settings';
describe('UserSettings', () => {
let component: UserSettings;
let fixture: ComponentFixture<UserSettings>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UserSettings]
})
.compileComponents();
fixture = TestBed.createComponent(UserSettings);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,9 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-user-settings',
imports: [],
templateUrl: './user-settings.html',
styleUrl: './user-settings.scss',
})
export class UserSettings {}