New Angular based web version #1

Closed
thomas.nuyken wants to merge 150 commits from main into ddd
5 changed files with 179 additions and 36 deletions
Showing only changes of commit 297af2b95d - Show all commits

View File

@@ -0,0 +1,89 @@
@if (!loaded) {
<p-skeleton height="4rem" styleClass="mb-2" />
} @else {
<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">
<label for="rabbit"> Kaninchen </label>
@if (rabbits$ | async; as rabbits) {
<p-select
[options]="rabbits"
placeholder="Kaninchen auswählen"
formControlName="rabbit"
optionLabel="name"
inputId="rabbit"
styleClass="w-full" />
}
</div>
<div class="flex flex-col gap-2">
<label for="medicines"> Medizin </label>
@if (medicines$ | async; as medicines) {
<p-multiSelect
[options]="medicines"
[showToggleAll]="false"
[showHeader]="false"
[autoOptionFocus]="false"
[filter]="false"
[showClear]="true"
[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 class="flex flex-col gap-2">
<label for="weight"> Gewicht </label>
<p-inputGroup>
<input id="weight" placeholder="Gewicht eingeben" type="number" min="1" pInputText formControlName="weight" />
<p-inputGroupAddon>g</p-inputGroupAddon>
</p-inputGroup>
</div>
<div class="flex flex-col gap-2">
<label for="comment"> Kommentar </label>
<input pInputText id="comment" placeholder="Kommentar eingeben" type="text" formControlName="comment"
class="w-full" />
</div>
<div class="flex gap-2">
<p-button type="button" label="Abbrechen" (click)="navigateToOverviewPage()" severity="warn" />
<p-button type="submit" label="Abschicken" severity="success" [disabled]="formGroup.invalid" />
</div>
</form>
}

View File

@@ -0,0 +1,50 @@
import { AsyncPipe } from '@angular/common';
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { ButtonModule } from 'primeng/button';
import { ChipModule } from 'primeng/chip';
import { DatePickerModule } from 'primeng/datepicker';
import { FloatLabelModule } from 'primeng/floatlabel';
import { InputGroupModule } from 'primeng/inputgroup';
import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
import { InputNumberModule } from 'primeng/inputnumber';
import { InputTextModule } from 'primeng/inputtext';
import { MultiSelectModule } from 'primeng/multiselect';
import { SelectModule } from 'primeng/select';
import { SkeletonModule } from 'primeng/skeleton';
@Component({
selector: 'app-edit-entry',
imports: [
AsyncPipe,
ButtonModule,
ChipModule,
DatePickerModule,
FloatLabelModule,
InputGroupAddonModule,
InputGroupModule,
InputNumberModule,
InputTextModule,
MultiSelectModule,
ReactiveFormsModule,
SelectModule,
SkeletonModule,
],
templateUrl: './edit-entry.component.html',
styleUrl: './edit-entry.component.scss'
})
export class EditEntryComponent {
private readonly formBuilder = inject(FormBuilder);
protected readonly formGroup = this.formBuilder.group({
date: [<Date | null>null],
time: [<Date | null>null],
rabbit: [<Rabbit | null>null, Validators.required],
weight: [
<number | null>null,
Validators.min(1),
],
medicines: [<Medicine[]>[]],
comment: [<string | null>null],
});
}

View File

@@ -2,30 +2,33 @@
<p-scrollTop /> <p-scrollTop />
<div class="mb-4 flex gap-2 md:justify-between"> <div class="mb-4 flex gap-2 md:justify-between">
<div class="basis-full lg:basis-1/4 md:basis-1/2 p-0"> <div class="basis-full lg:basis-1/4 md:basis-1/2 p-0">
<p-select styleClass="w-full" [formControl]="selectedRabbit" placeholder="Kaninchen" [showClear]="true" <!-- <p-select styleClass="w-full" [formControl]="selectedRabbit" placeholder="Kaninchen" [showClear]="true"
[options]="(rabbits$ | async)!" optionLabel="name" /> [options]="(rabbits$ | async)!" optionLabel="name" /> -->
</div> </div>
<div> <div>
<p-button label="Erstellen" routerLink="/weight-entries/create"> <p-button label="Erstellen" routerLink="/weight-entries/create">
<ng-icon name="matAddSharp"></ng-icon> <!-- <ng-icon name="matAddSharp"></ng-icon> -->
</p-button> </p-button>
</div> </div>
</div> </div>
<div> <div>
@if (filteredWeightEntries$ | async; as weightEntries) { @if (consumptionEntries$ | async; as entries) {
<p-dataView [value]="weightEntries" <p-dataView
[value]="entries"
[paginator]="true" [paginator]="true"
[rows]="rowsPerPageDefaultOption" [rows]="rowsPerPageDefaultOption"
[rowsPerPageOptions]="rowsPerPageOptions" [rowsPerPageOptions]="rowsPerPageOptions"
[pageLinks]="0" [pageLinks]="0"
[showCurrentPageReport]="true" [showCurrentPageReport]="true"
[currentPageReportTemplate]="currentPageReportTemplate" [currentPageReportTemplate]="currentPageReportTemplate"
layout="list"> layout="list"
>
<ng-template #list let-entries> <ng-template #list let-entries>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@for (weightEntry of entries; track weightEntry.id) { @for (entry of entries; track entry.id) {
<app-weight-entry-card [weightEntry]="weightEntry" {{ entry | json }}
(entryDeleted)="onEntryDeleted($event)"></app-weight-entry-card> <!-- <app-weight-entry-card [weightEntry]="weightEntry"
(entryDeleted)="onEntryDeleted($event)"></app-weight-entry-card> -->
} }
</div> </div>
</ng-template> </ng-template>

View File

@@ -1,24 +1,19 @@
import { CommonModule } from '@angular/common'; import { 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 { 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 { Client, GetConsumptions_ResponseDto } from '../../../shared/api/swagger.generated';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'app-entries', selector: 'app-entries',
@@ -36,18 +31,24 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
styleUrl: './entries.component.scss' styleUrl: './entries.component.scss'
}) })
export class EntriesComponent { export class EntriesComponent {
private readonly http = inject(HttpClient); private readonly client = inject(Client);
protected readonly consumptionEntries$: Observable<ConsumptionEntry[]>; protected readonly consumptionEntries$: Observable<GetConsumptions_ResponseDto[] | undefined>;
protected readonly rowsPerPageDefaultOption = 25;
protected readonly rowsPerPageOptions = [10, 25, 50, 100];
protected readonly currentPageReportTemplate = '{currentPage} / {totalPages}';
protected readonly skeletonsIterationSource = Array(10).fill(0);
constructor() { constructor() {
this.consumptionEntries$ = this.http.get<GetConsumptionEntriesResponse>('/api/v1/consumptions') this.consumptionEntries$ = this.client.consumptionsGET()
.pipe( .pipe(
takeUntilDestroyed(), takeUntilDestroyed(),
tap((response) => { tap((response) => {
console.log('Entries response:', response); console.log('Entries response:', response);
}), }),
map(response => response.consumptions) map((response) => response.consumptions)
); )
} }
} }