Compare commits
3 Commits
321ffc3b7c
...
f173d46c2e
| Author | SHA1 | Date | |
|---|---|---|---|
| f173d46c2e | |||
| 73fbe30b3d | |||
| 229bfe0b79 |
@@ -1,7 +1,7 @@
|
|||||||
import {inject, Injectable} from "@angular/core";
|
import { HttpClient } from '@angular/common/http';
|
||||||
import {HttpClient} from '@angular/common/http';
|
import { inject, Injectable } from "@angular/core";
|
||||||
import { map, Observable } from 'rxjs';
|
import { map, Observable } from 'rxjs';
|
||||||
import {API_BASE_PATH} from '../api-base-path';
|
import { API_BASE_PATH } from "../api-base-path";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { environment } from '../../environments/environment';
|
import { environment } from '@vegasco-web/environments/environment';
|
||||||
import {
|
import {
|
||||||
provideKeycloak,
|
|
||||||
createInterceptorCondition,
|
|
||||||
IncludeBearerTokenCondition,
|
|
||||||
INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG,
|
|
||||||
withAutoRefreshToken,
|
|
||||||
AutoRefreshTokenService,
|
AutoRefreshTokenService,
|
||||||
UserActivityService
|
createInterceptorCondition,
|
||||||
|
INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG,
|
||||||
|
IncludeBearerTokenCondition,
|
||||||
|
provideKeycloak,
|
||||||
|
UserActivityService,
|
||||||
|
withAutoRefreshToken
|
||||||
} from 'keycloak-angular';
|
} from 'keycloak-angular';
|
||||||
|
|
||||||
const serverHostBearerInterceptorCondition = createInterceptorCondition<IncludeBearerTokenCondition>({
|
const serverHostBearerInterceptorCondition = createInterceptorCondition<IncludeBearerTokenCondition>({
|
||||||
|
|||||||
@@ -1,83 +1,59 @@
|
|||||||
@if (!loaded) {
|
@if (isLoading()) {
|
||||||
<p-skeleton height="4rem" styleClass="mb-2" />
|
<p-skeleton height="4rem" styleClass="mb-2" />
|
||||||
} @else {
|
} @else {
|
||||||
<form [formGroup]="formGroup" class="flex flex-col gap-4" (ngSubmit)="onSubmit()">
|
<form [formGroup]="formGroup" class="flex flex-col gap-4" (ngSubmit)="onSubmit()">
|
||||||
|
|
||||||
<div class="flex gap-2 w-full">
|
|
||||||
<div class="flex flex-col gap-2 w-full">
|
|
||||||
<label for="date"> Datum </label>
|
|
||||||
<p-datepicker [iconDisplay]="'input'"
|
|
||||||
[firstDayOfWeek]="1"
|
|
||||||
placeholder="Datum auswählen"
|
|
||||||
[showIcon]="true"
|
|
||||||
inputId="date"
|
|
||||||
formControlName="date"
|
|
||||||
styleClass="w-full"
|
|
||||||
dateFormat="dd.mm.yy" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-2 w-full">
|
|
||||||
<label for="time"> Uhrzeit </label>
|
|
||||||
<p-datepicker [iconDisplay]="'input'"
|
|
||||||
[showIcon]="true"
|
|
||||||
[timeOnly]="true"
|
|
||||||
placeholder="Uhrzeit auswählen"
|
|
||||||
inputId="time"
|
|
||||||
formControlName="time"
|
|
||||||
styleClass="w-full"
|
|
||||||
inputStyleClass="w-full" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label for="rabbit"> Kaninchen </label>
|
<label [for]="formFieldNames.car"> Auto </label>
|
||||||
@if (rabbits$ | async; as rabbits) {
|
@if (cars(); as cars) {
|
||||||
<p-select
|
<p-select
|
||||||
[options]="rabbits"
|
[options]="cars"
|
||||||
placeholder="Kaninchen auswählen"
|
placeholder="Auto auswählen"
|
||||||
formControlName="rabbit"
|
[formControlName]="formFieldNames.car"
|
||||||
optionLabel="name"
|
[optionLabel]="formFieldNames.car"
|
||||||
inputId="rabbit"
|
[inputId]="formFieldNames.car"
|
||||||
styleClass="w-full" />
|
styleClass="w-full" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label for="medicines"> Medizin </label>
|
<label [for]="formFieldNames.date"> Datum </label>
|
||||||
@if (medicines$ | async; as medicines) {
|
<p-datepicker [iconDisplay]="'input'"
|
||||||
<p-multiSelect
|
[firstDayOfWeek]="1"
|
||||||
[options]="medicines"
|
placeholder="Datum auswählen"
|
||||||
[showToggleAll]="false"
|
[showIcon]="true"
|
||||||
[showHeader]="false"
|
[inputId]="formFieldNames.date"
|
||||||
[autoOptionFocus]="false"
|
[formControlName]="formFieldNames.date"
|
||||||
[filter]="false"
|
styleClass="w-full"
|
||||||
[showClear]="true"
|
dateFormat="dd.mm.yy" />
|
||||||
[maxSelectedLabels]="medicines.length"
|
|
||||||
optionLabel="abbreviation"
|
|
||||||
formControlName="medicines"
|
|
||||||
inputId="medicines"
|
|
||||||
placeholder="Medizin auswählen"
|
|
||||||
display="chip"
|
|
||||||
styleClass="w-full">
|
|
||||||
<ng-template let-medicine pTemplate="item">
|
|
||||||
{{ medicine.name }} ({{ medicine.abbreviation }})
|
|
||||||
</ng-template>
|
|
||||||
</p-multiSelect>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label for="weight"> Gewicht </label>
|
<label [for]="formFieldNames.mileage"> Kilometerstand </label>
|
||||||
<p-inputGroup>
|
<p-inputGroup>
|
||||||
<input id="weight" placeholder="Gewicht eingeben" type="number" min="1" pInputText formControlName="weight" />
|
<input
|
||||||
<p-inputGroupAddon>g</p-inputGroupAddon>
|
id="mileage"
|
||||||
|
placeholder="Kilometerstand eingeben"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
pInputText
|
||||||
|
[formControlName]="formFieldNames.mileage" />
|
||||||
|
<p-inputGroupAddon>km</p-inputGroupAddon>
|
||||||
</p-inputGroup>
|
</p-inputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label for="comment"> Kommentar </label>
|
<label [for]="formFieldNames.amount"> Menge </label>
|
||||||
<input pInputText id="comment" placeholder="Kommentar eingeben" type="text" formControlName="comment"
|
<p-inputGroup>
|
||||||
class="w-full" />
|
<input
|
||||||
|
id="amount"
|
||||||
|
placeholder="Menge eingeben"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
pInputText
|
||||||
|
[formControlName]="formFieldNames.amount" />
|
||||||
|
<p-inputGroupAddon>l</p-inputGroupAddon>
|
||||||
|
</p-inputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { AsyncPipe } from '@angular/common';
|
import { Component, computed, inject, Signal } from '@angular/core';
|
||||||
import { Component, inject } from '@angular/core';
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { CarClient } from '@vegasco-web/api/cars/car-client';
|
||||||
import { ButtonModule } from 'primeng/button';
|
import { ButtonModule } from 'primeng/button';
|
||||||
import { ChipModule } from 'primeng/chip';
|
import { ChipModule } from 'primeng/chip';
|
||||||
import { DatePickerModule } from 'primeng/datepicker';
|
import { DatePickerModule } from 'primeng/datepicker';
|
||||||
@@ -12,11 +14,11 @@ import { InputTextModule } from 'primeng/inputtext';
|
|||||||
import { MultiSelectModule } from 'primeng/multiselect';
|
import { MultiSelectModule } from 'primeng/multiselect';
|
||||||
import { SelectModule } from 'primeng/select';
|
import { SelectModule } from 'primeng/select';
|
||||||
import { SkeletonModule } from 'primeng/skeleton';
|
import { SkeletonModule } from 'primeng/skeleton';
|
||||||
|
import { map } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit-entry',
|
selector: 'app-edit-entry',
|
||||||
imports: [
|
imports: [
|
||||||
AsyncPipe,
|
|
||||||
ButtonModule,
|
ButtonModule,
|
||||||
ChipModule,
|
ChipModule,
|
||||||
DatePickerModule,
|
DatePickerModule,
|
||||||
@@ -35,16 +37,133 @@ import { SkeletonModule } from 'primeng/skeleton';
|
|||||||
})
|
})
|
||||||
export class EditEntryComponent {
|
export class EditEntryComponent {
|
||||||
private readonly formBuilder = inject(FormBuilder);
|
private readonly formBuilder = inject(FormBuilder);
|
||||||
|
private readonly carClient = inject(CarClient);
|
||||||
|
private readonly router = inject(Router);
|
||||||
|
|
||||||
|
protected readonly formFieldNames = {
|
||||||
|
car: 'car',
|
||||||
|
date: 'date',
|
||||||
|
mileage: 'mileage',
|
||||||
|
amount: 'amount',
|
||||||
|
}
|
||||||
|
|
||||||
protected readonly formGroup = this.formBuilder.group({
|
protected readonly formGroup = this.formBuilder.group({
|
||||||
date: [<Date | null>null],
|
[this.formFieldNames.car]: [<Car | null>null, Validators.required],
|
||||||
time: [<Date | null>null],
|
[this.formFieldNames.date]: [<Date | null>null],
|
||||||
rabbit: [<Rabbit | null>null, Validators.required],
|
[this.formFieldNames.mileage]: [
|
||||||
weight: [
|
|
||||||
<number | null>null,
|
<number | null>null,
|
||||||
Validators.min(1),
|
[Validators.required, Validators.min(1)],
|
||||||
|
],
|
||||||
|
[this.formFieldNames.amount]: [
|
||||||
|
<number | null>null,
|
||||||
|
[Validators.required, Validators.min(1)],
|
||||||
],
|
],
|
||||||
medicines: [<Medicine[]>[]],
|
|
||||||
comment: [<string | null>null],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
protected readonly cars: Signal<Car[] | undefined>;
|
||||||
|
|
||||||
|
protected readonly isLoading = computed(() => {
|
||||||
|
return this.cars() === undefined;
|
||||||
|
})
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.cars = toSignal(
|
||||||
|
this.carClient
|
||||||
|
.getAll()
|
||||||
|
.pipe(
|
||||||
|
takeUntilDestroyed(),
|
||||||
|
map(response => response.cars)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async navigateToOverviewPage(): Promise<void> {
|
||||||
|
await this.router.navigateByUrl(`/entries`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(): void {
|
||||||
|
// if (!this.entryId) {
|
||||||
|
// this.createEntry();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.updateEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
createEntry() {
|
||||||
|
// this.api
|
||||||
|
// .createWeightEntry(
|
||||||
|
// this.getWeighedAt(),
|
||||||
|
// this.formGroup.controls['weight'].value,
|
||||||
|
// this.formGroup.controls['comment'].value,
|
||||||
|
// this.formGroup.controls['rabbit'].value!.id,
|
||||||
|
// this.formGroup.controls['medicines'].value?.map((x) => x.id) ?? [],
|
||||||
|
// )
|
||||||
|
// .subscribe({
|
||||||
|
// next: (_) => {
|
||||||
|
// this.router.navigateByUrl('/weight-entries');
|
||||||
|
// },
|
||||||
|
// error: (error: HttpErrorResponse) => {
|
||||||
|
// 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;
|
||||||
|
// case error.status == 400:
|
||||||
|
// this.messageService.add({
|
||||||
|
// severity: 'error',
|
||||||
|
// summary: 'Clientfehler',
|
||||||
|
// detail:
|
||||||
|
// 'Die Anwendung scheint falsche Daten an den Server zu senden.',
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEntry() {
|
||||||
|
// this.api
|
||||||
|
// .updateWeightEntry(
|
||||||
|
// this.entryId!,
|
||||||
|
// this.getWeighedAt(),
|
||||||
|
// this.formGroup.controls['weight'].value,
|
||||||
|
// this.formGroup.controls['comment'].value,
|
||||||
|
// this.formGroup.controls['rabbit'].value!.id,
|
||||||
|
// this.formGroup.controls['medicines'].value?.map((x) => x.id) ?? [],
|
||||||
|
// )
|
||||||
|
// .subscribe({
|
||||||
|
// next: (_) => {
|
||||||
|
// this.router.navigateByUrl('/weight-entries');
|
||||||
|
// },
|
||||||
|
// error: (error: HttpErrorResponse) => {
|
||||||
|
// switch (true) {
|
||||||
|
// case error.status >= 500 && error.status <= 599:
|
||||||
|
// this.messageService.add({
|
||||||
|
// severity: 'error',
|
||||||
|
// summary: 'Serverfehler',
|
||||||
|
// detail:
|
||||||
|
// 'Beim Aktualisieren des Eintrags ist ein Fehler aufgetreten. Bitte versuche es erneut.',
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// case error.status == 400:
|
||||||
|
// this.messageService.add({
|
||||||
|
// severity: 'error',
|
||||||
|
// summary: 'Clientfehler',
|
||||||
|
// detail:
|
||||||
|
// 'Die Anwendung scheint falsche Daten an den Server zu senden.',
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,11 @@
|
|||||||
<p-dataView
|
<p-dataView
|
||||||
[value]="entries"
|
[value]="entries"
|
||||||
[paginator]="true"
|
[paginator]="true"
|
||||||
[rows]="rowsPerPageDefaultOption"
|
[rows]="25"
|
||||||
[rowsPerPageOptions]="rowsPerPageOptions"
|
[rowsPerPageOptions]="[10, 25, 50, 100]"
|
||||||
[pageLinks]="0"
|
[pageLinks]="0"
|
||||||
[showCurrentPageReport]="true"
|
[showCurrentPageReport]="true"
|
||||||
[currentPageReportTemplate]="currentPageReportTemplate"
|
currentPageReportTemplate="{currentPage} / {totalPages}"
|
||||||
layout="list"
|
layout="list"
|
||||||
>
|
>
|
||||||
<ng-template #list let-entries>
|
<ng-template #list let-entries>
|
||||||
|
|||||||
@@ -1,26 +1,20 @@
|
|||||||
import { AsyncPipe, CommonModule } from '@angular/common';
|
import { AsyncPipe, CommonModule } from '@angular/common';
|
||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
import { MessageService } from 'primeng/api';
|
import { CarClient } from '@vegasco-web/api/cars/car-client';
|
||||||
|
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
||||||
import { ButtonModule } from 'primeng/button';
|
import { ButtonModule } from 'primeng/button';
|
||||||
import { DataViewModule } from 'primeng/dataview';
|
import { DataViewModule } from 'primeng/dataview';
|
||||||
import { SelectModule } from 'primeng/select';
|
|
||||||
import { ScrollTopModule } from 'primeng/scrolltop';
|
import { ScrollTopModule } from 'primeng/scrolltop';
|
||||||
|
import { SelectModule } from 'primeng/select';
|
||||||
import { SkeletonModule } from 'primeng/skeleton';
|
import { SkeletonModule } from 'primeng/skeleton';
|
||||||
import {
|
import {
|
||||||
BehaviorSubject,
|
|
||||||
combineLatest,
|
|
||||||
map,
|
map,
|
||||||
Observable,
|
Observable,
|
||||||
of,
|
tap
|
||||||
startWith,
|
|
||||||
tap,
|
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { HttpClient } from '@angular/common/http';
|
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
||||||
import {CarClient} from '../../../api/cars/car-client';
|
|
||||||
import {ConsumptionClient} from '../../../api/consumptions/consumption-client';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-entries',
|
selector: 'app-entries',
|
||||||
@@ -45,6 +39,8 @@ export class EntriesComponent {
|
|||||||
protected readonly consumptionEntries$: Observable<ConsumptionEntry[]>;
|
protected readonly consumptionEntries$: Observable<ConsumptionEntry[]>;
|
||||||
protected readonly cars$: Observable<Car[]>;
|
protected readonly cars$: Observable<Car[]>;
|
||||||
|
|
||||||
|
protected readonly skeletonsIterationSource = Array(10).fill(0);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.consumptionEntries$ = this.consumptionClient.getAll()
|
this.consumptionEntries$ = this.consumptionClient.getAll()
|
||||||
.pipe(
|
.pipe(
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@vegasco-web/*": ["src/app/*"],
|
||||||
|
"@vegasco-web/assets/*": ["assets/*"],
|
||||||
|
"@vegasco-web/environments/*": ["src/environments/*"]
|
||||||
|
},
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user