Add loading entry data when updating an entry
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, computed, DestroyRef, inject, input, 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 { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { CarClient } from '@vegasco-web/api/cars/car-client';
|
||||
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
||||
import { RoutingService } from '@vegasco-web/services/routing.service';
|
||||
@@ -17,7 +17,7 @@ import { InputTextModule } from 'primeng/inputtext';
|
||||
import { MultiSelectModule } from 'primeng/multiselect';
|
||||
import { SelectModule } from 'primeng/select';
|
||||
import { SkeletonModule } from 'primeng/skeleton';
|
||||
import { catchError, EMPTY, map, Observable, switchMap, throwError } from 'rxjs';
|
||||
import { catchError, combineLatest, EMPTY, filter, map, Observable, switchMap, tap, throwError } from 'rxjs';
|
||||
import { RequiredMarkerComponent } from './components/required-marker.component';
|
||||
|
||||
@Component({
|
||||
@@ -40,15 +40,14 @@ import { RequiredMarkerComponent } from './components/required-marker.component'
|
||||
templateUrl: './edit-entry.component.html',
|
||||
styleUrl: './edit-entry.component.scss'
|
||||
})
|
||||
export class EditEntryComponent {
|
||||
private readonly formBuilder = inject(FormBuilder);
|
||||
export class EditEntryComponent implements OnInit {
|
||||
private readonly carClient = inject(CarClient);
|
||||
private readonly consumptionClient = inject(ConsumptionClient);
|
||||
private readonly routingService = inject(RoutingService);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly messageService = inject(MessageService);
|
||||
|
||||
protected readonly entryId = input<string | undefined>(undefined);
|
||||
protected readonly id = input<string | undefined>(undefined);
|
||||
|
||||
protected readonly formFieldNames = {
|
||||
car: 'car',
|
||||
@@ -57,34 +56,82 @@ export class EditEntryComponent {
|
||||
amount: 'amount',
|
||||
} as const;
|
||||
|
||||
protected readonly formGroup = this.formBuilder.group({
|
||||
[this.formFieldNames.car]: [<Car | null>null, Validators.required],
|
||||
[this.formFieldNames.date]: [<Date>new Date(), Validators.required],
|
||||
[this.formFieldNames.mileage]: [
|
||||
<number | null>null,
|
||||
[Validators.required, Validators.min(1)],
|
||||
],
|
||||
[this.formFieldNames.amount]: [
|
||||
<number | null>null,
|
||||
[Validators.required, Validators.min(1)],
|
||||
],
|
||||
protected readonly formGroup = new FormGroup({
|
||||
[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.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)]),
|
||||
});
|
||||
|
||||
private readonly cars$: Observable<Car[]>;
|
||||
protected readonly cars: Signal<Car[] | undefined>;
|
||||
|
||||
private readonly isEntryDataLoaded = signal(false);
|
||||
|
||||
protected readonly isLoading = computed(() => {
|
||||
return this.cars() === undefined;
|
||||
})
|
||||
var cars = this.cars();
|
||||
var isEntryDataLoaded = this.isEntryDataLoaded();
|
||||
return cars === undefined || !isEntryDataLoaded;
|
||||
});
|
||||
|
||||
constructor() {
|
||||
this.cars = toSignal(
|
||||
this.carClient
|
||||
this.cars$ = this.carClient
|
||||
.getAll()
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
map(response => response.cars)
|
||||
),
|
||||
);
|
||||
this.cars = toSignal(this.cars$);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadEntryDetailsAndEnableControls();
|
||||
}
|
||||
|
||||
private loadEntryDetailsAndEnableControls() {
|
||||
const entryId = this.id();
|
||||
|
||||
if (entryId === undefined || entryId === null) {
|
||||
this.enableFormControls();
|
||||
this.isEntryDataLoaded.set(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const consumption$ = this.consumptionClient
|
||||
.getSingle(entryId);
|
||||
|
||||
combineLatest([
|
||||
consumption$, this.cars$
|
||||
])
|
||||
.pipe(
|
||||
filter(([_, cars]) => cars !== undefined),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
catchError((error) => this.handleGetError(error)),
|
||||
tap(([consumption, cars]) => {
|
||||
this.formGroup.patchValue({
|
||||
[this.formFieldNames.car]: cars!.find(c => c.id === consumption.carId) ?? null,
|
||||
[this.formFieldNames.date]: new Date(consumption.dateTime),
|
||||
[this.formFieldNames.mileage]: consumption.distance,
|
||||
[this.formFieldNames.amount]: consumption.amount,
|
||||
});
|
||||
}),
|
||||
tap(() => {
|
||||
this.enableFormControls();
|
||||
this.isEntryDataLoaded.set(true);
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private enableFormControls(): void {
|
||||
for (const controlName of Object.values(this.formFieldNames)) {
|
||||
const control = this.formGroup.get(controlName);
|
||||
if (control) {
|
||||
control.enable();
|
||||
} else {
|
||||
console.warn(`Form control '${controlName}' not found.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async navigateToOverviewPage(): Promise<void> {
|
||||
@@ -92,7 +139,7 @@ export class EditEntryComponent {
|
||||
}
|
||||
|
||||
onSubmit(): void {
|
||||
var entryId = this.entryId();
|
||||
var entryId = this.id();
|
||||
if (entryId === undefined || entryId === null) {
|
||||
this.createEntry();
|
||||
return;
|
||||
@@ -118,7 +165,7 @@ export class EditEntryComponent {
|
||||
this.consumptionClient.create(request)
|
||||
.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
catchError((error) => this.handleError(error)),
|
||||
catchError((error) => this.handleCreateOrUpdateError(error)),
|
||||
switchMap(() => this.routingService.navigateToEntries())
|
||||
)
|
||||
.subscribe();
|
||||
@@ -129,13 +176,41 @@ export class EditEntryComponent {
|
||||
this.consumptionClient.update(id, request)
|
||||
.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
catchError((error) => this.handleError(error)),
|
||||
catchError((error) => this.handleCreateOrUpdateError(error)),
|
||||
switchMap(() => this.routingService.navigateToEntries())
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private handleError(error: unknown): Observable<never> {
|
||||
private handleGetError(error: unknown): Observable<never> {
|
||||
if (!(error instanceof HttpErrorResponse)) {
|
||||
return throwError(() => error);
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case error.status >= 500 && error.status <= 599:
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Serverfehler',
|
||||
detail:
|
||||
'Beim Erstellen des Eintrags ist ein Fehler aufgetreten. Bitte versuche es erneut.',
|
||||
});
|
||||
break;
|
||||
default:
|
||||
console.error(error);
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Unerwarteter Fehler',
|
||||
detail:
|
||||
'Beim Erstellen des Eintrags hat der Server eine unerwartete Antwort zurückgegeben.',
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
private handleCreateOrUpdateError(error: unknown): Observable<never> {
|
||||
if (!(error instanceof HttpErrorResponse)) {
|
||||
return throwError(() => error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user