This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
"@ng-icons/material-icons": "^31.4.0",
|
"@ng-icons/material-icons": "^31.4.0",
|
||||||
"@primeng/themes": "^19.1.3",
|
"@primeng/themes": "^19.1.3",
|
||||||
"@tailwindcss/postcss": "^4.1.10",
|
"@tailwindcss/postcss": "^4.1.10",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"keycloak-angular": "^19.0.2",
|
"keycloak-angular": "^19.0.2",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"primeng": "^19.1.3",
|
"primeng": "^19.1.3",
|
||||||
|
|||||||
8
src/Vegasco-Web/pnpm-lock.yaml
generated
8
src/Vegasco-Web/pnpm-lock.yaml
generated
@@ -41,6 +41,9 @@ importers:
|
|||||||
'@tailwindcss/postcss':
|
'@tailwindcss/postcss':
|
||||||
specifier: ^4.1.10
|
specifier: ^4.1.10
|
||||||
version: 4.1.10
|
version: 4.1.10
|
||||||
|
dayjs:
|
||||||
|
specifier: ^1.11.13
|
||||||
|
version: 1.11.13
|
||||||
keycloak-angular:
|
keycloak-angular:
|
||||||
specifier: ^19.0.2
|
specifier: ^19.0.2
|
||||||
version: 19.0.2(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/animations@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(keycloak-js@26.2.0)
|
version: 19.0.2(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/router@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.14(@angular/animations@19.2.14(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.14(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.14(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(keycloak-js@26.2.0)
|
||||||
@@ -2229,6 +2232,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==}
|
resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
|
||||||
|
dayjs@1.11.13:
|
||||||
|
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -6763,6 +6769,8 @@ snapshots:
|
|||||||
|
|
||||||
date-format@4.0.14: {}
|
date-format@4.0.14: {}
|
||||||
|
|
||||||
|
dayjs@1.11.13: {}
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.0.0
|
ms: 2.0.0
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
[firstDayOfWeek]="1"
|
[firstDayOfWeek]="1"
|
||||||
placeholder="Datum auswählen"
|
placeholder="Datum auswählen"
|
||||||
[showIcon]="true"
|
[showIcon]="true"
|
||||||
|
[maxDate]="today"
|
||||||
|
[defaultDate]="today"
|
||||||
[inputId]="formFieldNames.date"
|
[inputId]="formFieldNames.date"
|
||||||
[formControlName]="formFieldNames.date"
|
[formControlName]="formFieldNames.date"
|
||||||
styleClass="w-full"
|
styleClass="w-full"
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import dayjs from 'dayjs';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
import { Component, computed, DestroyRef, inject, input, OnInit, signal, Signal } from '@angular/core';
|
import { Component, computed, DestroyRef, inject, input, OnInit, signal, Signal } from '@angular/core';
|
||||||
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, ReactiveFormsModule, ValidationErrors, Validators } from '@angular/forms';
|
||||||
import { CarClient } from '@vegasco-web/api/cars/car-client';
|
import { CarClient } from '@vegasco-web/api/cars/car-client';
|
||||||
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
||||||
import { RoutingService } from '@vegasco-web/services/routing.service';
|
import { RoutingService } from '@vegasco-web/services/routing.service';
|
||||||
@@ -51,6 +52,8 @@ export class EditEntryComponent implements OnInit {
|
|||||||
|
|
||||||
protected readonly id = input<string | undefined>(undefined);
|
protected readonly id = input<string | undefined>(undefined);
|
||||||
|
|
||||||
|
protected readonly today = new Date();
|
||||||
|
|
||||||
protected readonly formFieldNames = {
|
protected readonly formFieldNames = {
|
||||||
car: 'car',
|
car: 'car',
|
||||||
date: 'date',
|
date: 'date',
|
||||||
@@ -60,7 +63,7 @@ export class EditEntryComponent implements OnInit {
|
|||||||
|
|
||||||
protected readonly formGroup = new FormGroup({
|
protected readonly formGroup = new FormGroup({
|
||||||
[this.formFieldNames.car]: new FormControl<Car | null>({ value: null, disabled: true }, [Validators.required]),
|
[this.formFieldNames.car]: new FormControl<Car | null>({ value: null, disabled: true }, [Validators.required]),
|
||||||
[this.formFieldNames.date]: new FormControl<Date>({ value: new Date(), disabled: true }, [Validators.required]),
|
[this.formFieldNames.date]: new FormControl<Date>({ value: new Date(), disabled: true }, [Validators.required, this.dateTimeGreaterThanOrEqualToTodayValidator]),
|
||||||
[this.formFieldNames.mileage]: new FormControl<number | null>({ value: null, disabled: true }, [Validators.required, Validators.min(1)]),
|
[this.formFieldNames.mileage]: new FormControl<number | null>({ value: null, disabled: true }, [Validators.required, Validators.min(1)]),
|
||||||
[this.formFieldNames.amount]: new FormControl<number | null>({ value: null, disabled: true }, [Validators.required, Validators.min(1)]),
|
[this.formFieldNames.amount]: new FormControl<number | null>({ value: null, disabled: true }, [Validators.required, Validators.min(1)]),
|
||||||
});
|
});
|
||||||
@@ -271,4 +274,15 @@ export class EditEntryComponent implements OnInit {
|
|||||||
|
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private dateTimeGreaterThanOrEqualToTodayValidator(control: FormControl<Date>): ValidationErrors | null {
|
||||||
|
const tomorrowStartOfDay = dayjs().add(1, 'day').startOf('day');
|
||||||
|
const controlDate = dayjs(control.value);
|
||||||
|
|
||||||
|
if (controlDate.isBefore(tomorrowStartOfDay)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { dateTimeGreaterThanOrEqualToToday: true };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export class EntryCardComponent {
|
|||||||
const formatted = entry.literPer100Km
|
const formatted = entry.literPer100Km
|
||||||
?.toFixed(2)
|
?.toFixed(2)
|
||||||
.replace('.', ',');
|
.replace('.', ',');
|
||||||
console.log('Formatted liter per 100km:', formatted);
|
|
||||||
return formatted;
|
return formatted;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,13 @@ public static class CreateConsumption
|
|||||||
{
|
{
|
||||||
public Validator(TimeProvider timeProvider)
|
public Validator(TimeProvider timeProvider)
|
||||||
{
|
{
|
||||||
|
DateTime todayEndOfDay = timeProvider.GetUtcNow()
|
||||||
|
.Date
|
||||||
|
.AddDays(1)
|
||||||
|
.AddTicks(-1);
|
||||||
|
|
||||||
RuleFor(x => x.DateTime.ToUniversalTime())
|
RuleFor(x => x.DateTime.ToUniversalTime())
|
||||||
.LessThanOrEqualTo(timeProvider.GetUtcNow())
|
.LessThanOrEqualTo(todayEndOfDay)
|
||||||
.WithName(nameof(Request.DateTime));
|
.WithName(nameof(Request.DateTime));
|
||||||
|
|
||||||
RuleFor(x => x.Distance)
|
RuleFor(x => x.Distance)
|
||||||
@@ -70,6 +75,7 @@ public static class CreateConsumption
|
|||||||
await dbContext.SaveChangesAsync(cancellationToken);
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
return TypedResults.Created($"consumptions/{consumption.Id.Value}",
|
return TypedResults.Created($"consumptions/{consumption.Id.Value}",
|
||||||
new Response(consumption.Id.Value, consumption.DateTime, consumption.Distance, consumption.Amount, consumption.CarId.Value));
|
new Response(consumption.Id.Value, consumption.DateTime, consumption.Distance, consumption.Amount,
|
||||||
|
consumption.CarId.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,8 +26,13 @@ public static class UpdateConsumption
|
|||||||
{
|
{
|
||||||
public Validator(TimeProvider timeProvider)
|
public Validator(TimeProvider timeProvider)
|
||||||
{
|
{
|
||||||
|
DateTime todayEndOfDay = timeProvider.GetUtcNow()
|
||||||
|
.Date
|
||||||
|
.AddDays(1)
|
||||||
|
.AddTicks(-1);
|
||||||
|
|
||||||
RuleFor(x => x.DateTime.ToUniversalTime())
|
RuleFor(x => x.DateTime.ToUniversalTime())
|
||||||
.LessThanOrEqualTo(timeProvider.GetUtcNow())
|
.LessThanOrEqualTo(todayEndOfDay)
|
||||||
.WithName(nameof(Request.DateTime));
|
.WithName(nameof(Request.DateTime));
|
||||||
|
|
||||||
RuleFor(x => x.Distance)
|
RuleFor(x => x.Distance)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class CreateConsumptionRequestValidatorTests
|
|||||||
_sut = new CreateConsumption.Validator(_timeProvider);
|
_sut = new CreateConsumption.Validator(_timeProvider);
|
||||||
|
|
||||||
_validRequest = new CreateConsumption.Request(
|
_validRequest = new CreateConsumption.Request(
|
||||||
_utcNow.AddDays(-1),
|
_utcNow.Date.AddDays(1).AddTicks(-1),
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
Guid.NewGuid());
|
Guid.NewGuid());
|
||||||
@@ -38,10 +38,10 @@ public class CreateConsumptionRequestValidatorTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ValidateAsync_ShouldBeInvalid_WhenDateTimeIsGreaterThanUtcNow()
|
public async Task ValidateAsync_ShouldBeInvalid_WhenDateTimeIsGreaterThanUtcToday()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
CreateConsumption.Request request = _validRequest with { DateTime = _utcNow.AddDays(1) };
|
CreateConsumption.Request request = _validRequest with { DateTime = _utcNow.Date.AddDays(1) };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ValidationResult? result = await _sut.ValidateAsync(request);
|
ValidationResult? result = await _sut.ValidateAsync(request);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class UpdateConsumptionRequestValidatorTests
|
|||||||
_sut = new UpdateConsumption.Validator(_timeProvider);
|
_sut = new UpdateConsumption.Validator(_timeProvider);
|
||||||
|
|
||||||
_validRequest = new UpdateConsumption.Request(
|
_validRequest = new UpdateConsumption.Request(
|
||||||
_utcNow.AddDays(-1),
|
_utcNow.Date.AddDays(1).AddTicks(-1),
|
||||||
1,
|
1,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
@@ -38,10 +38,10 @@ public class UpdateConsumptionRequestValidatorTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ValidateAsync_ShouldBeInvalid_WhenDateTimeIsGreaterThanUtcNow()
|
public async Task ValidateAsync_ShouldBeInvalid_WhenDateTimeIsGreaterThanUtcToday()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
UpdateConsumption.Request request = _validRequest with { DateTime = _utcNow.AddDays(1) };
|
UpdateConsumption.Request request = _validRequest with { DateTime = _utcNow.Date.AddDays(1) };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
ValidationResult? result = await _sut.ValidateAsync(request);
|
ValidationResult? result = await _sut.ValidateAsync(request);
|
||||||
|
|||||||
Reference in New Issue
Block a user