UI improvments

This commit is contained in:
nessar committed 2026-10-02 15:05:30 +02:00
1 parent c9dbe82b79
commit 0ce33cc9d6
106 files changed
+72934 -1675

No files matched your search

+30 -44
View File
@@ -1,9 +1,9 @@
import {
Component,
ChangeDetectionStrategy,
ChangeDetectorRef,
inject,
signal,
Injectable,
effect,
} from '@angular/core';
import {
@@ -25,37 +25,11 @@ import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { FormsModule } from '@angular/forms';
import { LiveAnnouncer } from '@angular/cdk/a11y';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
NativeDateAdapter,
} from '@angular/material/core';
import { CdkDragDrop, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
@Injectable()
class CustomDateAdapter extends NativeDateAdapter {
override format(date: Date, displayFormat: unknown): string {
if (displayFormat === 'input') {
const day = date.getDate().toString().padStart(2, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear();
return `${day}/${month}/${year}`;
}
return super.format(date, displayFormat as object);
}
}
const MY_DATE_FORMATS = {
parse: { dateInput: 'input' },
display: {
dateInput: 'input',
monthYearLabel: { year: 'numeric', month: 'short' },
dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
monthYearA11yLabel: { year: 'numeric', month: 'long' },
},
};
import { DateAdapter } from '@angular/material/core';
import { DAY_FIRST_DATE_PROVIDERS } from '../../shared/day-first-date-adapter';
import { CdkDragDrop, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
@Component({
selector: 'app-rules-panel',
@@ -71,20 +45,19 @@ const MY_DATE_FORMATS = {
FormsModule,
CdkDropList,
CdkDrag,
CdkDragHandle,
],
templateUrl: './rules-panel.html',
styleUrl: './rules-panel.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{ provide: DateAdapter, useClass: CustomDateAdapter },
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS },
],
providers: DAY_FIRST_DATE_PROVIDERS,
})
export class RulesPanel {
public ruleService = inject(RuleService);
protected readonly translationService = inject(TranslationService);
private readonly dateAdapter = inject(DateAdapter);
private readonly liveAnnouncer = inject(LiveAnnouncer);
private readonly changeDetector = inject(ChangeDetectorRef);
get tr() {
return this.translationService.tr;
@@ -145,16 +118,30 @@ export class RulesPanel {
}
public drop(event: CdkDragDrop<VacationRule[]>) {
if (event.previousIndex !== event.currentIndex) {
this.ruleService.reorderRules(event.previousIndex, event.currentIndex);
if (event.isPointerOverContainer && event.previousIndex !== event.currentIndex) {
this.reorderRule(event.previousIndex, event.currentIndex);
}
// CDK restores the original DOM before this callback. Commit the final order
// before the next paint so zoneless rendering doesn't flash the old position.
this.changeDetector.detectChanges();
}
public moveRule(index: number, offset: -1 | 1, event: Event) {
event.stopPropagation();
const destination = index + offset;
if (destination >= 0 && destination < this.rules.length)
this.ruleService.reorderRules(index, destination);
this.reorderRule(index, destination);
}
private reorderRule(from: number, to: number) {
const rule = this.rules[from];
this.ruleService.reorderRules(from, to);
void this.liveAnnouncer.announce(
this.tr()
.rules.ruleMoved.replace('{name}', rule.name)
.replace('{position}', String(to + 1))
.replace('{count}', String(this.rules.length)),
);
}
public toggleRule(id: string) {
@@ -229,7 +216,6 @@ export class RulesPanel {
public getRuleSummary(rule: VacationRule): string {
const tr = this.tr();
const forceLabel = rule.force === 'obligation' ? tr.rules.obligation : tr.rules.preference;
if (rule.type === RuleType.IF_THEN) {
const ifThen = rule as IfThenRule;
const dayLabel = this.daysOfWeek.find((d) => d.value === ifThen.dayOfWeek)?.label ?? '';
@@ -241,13 +227,13 @@ export class RulesPanel {
.toLowerCase();
const rewardTypeLabel = this.getDayTypeLabel(ifThen.rewardType);
return `[${forceLabel}] ${tr.rules.ifThenTemplate
return tr.rules.ifThenTemplate
.replace('{day}', dayLabel)
.replace('{placeDays}', String(ifThen.placeDays))
.replace('{placeType}', placeTypeLabel)
.replace('{placement}', placementLabel)
.replace('{rewardDays}', String(ifThen.rewardDays))
.replace('{rewardType}', rewardTypeLabel)}`;
.replace('{rewardType}', rewardTypeLabel);
} else {
const timeWindow = rule as TimeWindowRule;
const placeTypeLabel = this.getDayTypeLabel(timeWindow.placeType);
@@ -258,11 +244,11 @@ export class RulesPanel {
this.translationService.locale(),
);
return `[${forceLabel}] ${tr.rules.timeWindowTemplate
return tr.rules.timeWindowTemplate
.replace('{placeDays}', String(timeWindow.placeDays))
.replace('{placeType}', placeTypeLabel)
.replace('{startDate}', startDateStr)
.replace('{endDate}', endDateStr)}`;
.replace('{endDate}', endDateStr);
}
}
}