add calendar settings
This commit is contained in:
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;
|
||||
}
|
||||
@@ -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 {}
|
||||
Reference in new issue
Block a user