feat: enhance user input component with new styling and functionality

- Added informational styling to warning cards in user input component.
- Improved remaining days details and history display with new computed properties.
- Updated user input service to manage planning outcomes and traces more effectively.
- Enhanced leave planner service to classify remaining balances with detailed reasons.
- Expanded translation service to support new balance reasoning and suggestions.
- Updated translations for multiple languages to reflect new features and terminology.
This commit is contained in:
nessar committed 2026-10-07 21:49:33 +02:00
1 parent 9851edf906
commit 3dc601982a
15 files changed
+679 -141

No files matched your search

+37 -11
View File
@@ -1,6 +1,8 @@
/// <reference types="vite/client" />
import { Injectable, inject, Injector, computed } from '@angular/core';
import { storedSignal } from '../shared/utils/stored-signal';
import type { PlanOutcome, RemainingBalance } from './leave-planner.service';
import { addPlanningDays } from './planning-date';
export interface AppTranslations {
locale: string;
@@ -27,7 +29,14 @@ export interface AppTranslations {
durationEstimate: string;
durationUnits: { seconds: string; minutes: string };
remainingDaysWarning: string;
remainingDaysManualPlace: string;
remainingWhy: string;
remainingValidity: string;
remainingHorizon: string;
remainingEarnedFrom: string;
remainingHistoryHelp: string;
remainingNoEvaluations: string;
remainingSuggestions: Record<string, string>;
remainingCandidateReasons: Record<string, string>;
deleteEntry: string;
chooseDate: string;
availableDate: string;
@@ -36,16 +45,6 @@ export interface AppTranslations {
daySuffix: string;
daysSuffix: string;
expires: string;
remainingClassification: {
unavoidableExpiry: string;
atRisk: string;
deferred: string;
};
remainingReason: {
unavoidableExpiry: string;
atRisk: string;
deferred: string;
};
};
dayTypes: {
weekend: string;
@@ -389,6 +388,33 @@ export class TranslationService {
return langCode.toUpperCase();
}
public formatPlanningDate(date: string): string {
return new Date(`${date}T00:00:00Z`).toLocaleDateString(this.locale(), {
timeZone: 'UTC',
day: 'numeric',
month: 'long',
year: 'numeric',
});
}
public getRemainingBalanceReason(
balance: RemainingBalance,
plan: PlanOutcome | undefined,
incomplete = false,
): string {
const reasons = this.tr().planning.details.remainingReasons;
if (!plan) return reasons['not-established'];
const code =
incomplete && ['preserved', 'not-established'].includes(balance.reason.code)
? 'calculation-incomplete'
: balance.reason.code;
return (reasons[code] ?? reasons['not-established'])
.replace('{available}', this.formatPlanningDate(balance.availableFrom))
.replace('{expiry}', this.formatPlanningDate(balance.expiryDate))
.replace('{start}', this.formatPlanningDate(plan.horizon.start))
.replace('{end}', this.formatPlanningDate(addPlanningDays(plan.horizon.end, -1)));
}
public getDayTypeLabel(type: string): string {
const tr = this.tr();
if (!tr || !tr.dayTypes) {