edit hinter button

This commit is contained in:
Bastian Wagner
2026-06-09 17:00:47 +02:00
parent 16605c961f
commit db525564c8
3 changed files with 104 additions and 40 deletions

View File

@@ -36,32 +36,44 @@
<mat-card class="editor-card" appearance="outlined">
<mat-card-header>
<mat-card-title>Details</mat-card-title>
@if (!isCreateMode()) {
<button mat-stroked-button type="button" (click)="showEditor() ? cancelEditing() : startEditing()">
<mat-icon aria-hidden="true">{{ showEditor() ? 'close' : 'edit' }}</mat-icon>
{{ showEditor() ? 'Abbrechen' : 'Bearbeiten' }}
</button>
}
</mat-card-header>
<mat-card-content>
<form [formGroup]="listForm" class="list-form" (ngSubmit)="saveList()">
<mat-form-field appearance="outline">
<mat-label>Titel</mat-label>
<input matInput formControlName="name" autocomplete="off" />
@if (listForm.controls.name.hasError('required')) {
<mat-error>Titel ist erforderlich.</mat-error>
}
</mat-form-field>
@if (showEditor()) {
<form [formGroup]="listForm" class="list-form" (ngSubmit)="saveList()">
<mat-form-field appearance="outline">
<mat-label>Titel</mat-label>
<input matInput formControlName="name" autocomplete="off" />
@if (listForm.controls.name.hasError('required')) {
<mat-error>Titel ist erforderlich.</mat-error>
}
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Beschreibung</mat-label>
<textarea matInput formControlName="description" rows="4"></textarea>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Beschreibung</mat-label>
<textarea matInput formControlName="description" rows="4"></textarea>
</mat-form-field>
<button mat-flat-button type="submit" [disabled]="saving()">
@if (saving()) {
<mat-progress-spinner mode="indeterminate" diameter="18" />
} @else {
<mat-icon aria-hidden="true">save</mat-icon>
}
{{ isCreateMode() ? 'Liste anlegen' : 'Speichern' }}
</button>
</form>
<button mat-flat-button type="submit" [disabled]="saving()">
@if (saving()) {
<mat-progress-spinner mode="indeterminate" diameter="18" />
} @else {
<mat-icon aria-hidden="true">save</mat-icon>
}
{{ isCreateMode() ? 'Liste anlegen' : 'Speichern' }}
</button>
</form>
} @else {
<div class="list-summary">
<p>{{ list()?.description || 'Keine Beschreibung hinterlegt.' }}</p>
</div>
}
</mat-card-content>
</mat-card>
@@ -78,26 +90,28 @@
</mat-card-header>
<mat-card-content>
<form [formGroup]="itemForm" class="item-form" (ngSubmit)="addItem()">
<mat-form-field appearance="outline">
<mat-label>Neues Item</mat-label>
<input matInput formControlName="title" autocomplete="off" [disabled]="!canEditItems()" />
@if (itemForm.controls.title.hasError('required')) {
<mat-error>Item-Titel ist erforderlich.</mat-error>
}
</mat-form-field>
@if (showEditor()) {
<form [formGroup]="itemForm" class="item-form" (ngSubmit)="addItem()">
<mat-form-field appearance="outline">
<mat-label>Neues Item</mat-label>
<input matInput formControlName="title" autocomplete="off" [disabled]="!canEditItems()" />
@if (itemForm.controls.title.hasError('required')) {
<mat-error>Item-Titel ist erforderlich.</mat-error>
}
</mat-form-field>
<mat-checkbox formControlName="required">Pflicht</mat-checkbox>
<mat-checkbox formControlName="required">Pflicht</mat-checkbox>
<button mat-flat-button type="submit" [disabled]="addingItem() || !canEditItems()">
@if (addingItem()) {
<mat-progress-spinner mode="indeterminate" diameter="18" />
} @else {
<mat-icon aria-hidden="true">add</mat-icon>
}
Hinzufügen
</button>
</form>
<button mat-flat-button type="submit" [disabled]="addingItem() || !canEditItems()">
@if (addingItem()) {
<mat-progress-spinner mode="indeterminate" diameter="18" />
} @else {
<mat-icon aria-hidden="true">add</mat-icon>
}
Hinzufügen
</button>
</form>
}
@if (!canEditItems()) {
<div class="inline-empty">
@@ -143,7 +157,7 @@
<a mat-button routerLink="/lists" class="secondary-back">
<mat-icon aria-hidden="true">arrow_back</mat-icon>
Zur Listenuebersicht
Zur Listenübersicht
</a>
}
</section>

View File

@@ -34,6 +34,16 @@
background: color-mix(in srgb, var(--mat-sys-surface-container-low) 94%, white);
}
.editor-card mat-card-header {
align-items: center;
justify-content: space-between;
gap: 0.75rem;
}
.editor-card mat-card-header button {
flex: 0 0 auto;
}
.list-form,
.item-form {
display: grid;
@@ -72,6 +82,17 @@
font-size: 48px;
}
.list-summary {
padding-top: 0.75rem;
}
.list-summary p {
margin: 0;
color: var(--mat-sys-on-surface-variant);
overflow-wrap: anywhere;
line-height: 1.45;
}
.error-state mat-icon {
color: var(--mat-sys-error);
}

View File

@@ -46,10 +46,12 @@ export class ListDetailComponent implements OnInit {
protected readonly isCreateMode = signal(false);
protected readonly loading = signal(true);
protected readonly saving = signal(false);
protected readonly editing = signal(false);
protected readonly addingItem = signal(false);
protected readonly errorMessage = signal<string | null>(null);
protected readonly updatingItemId = signal<string | null>(null);
protected readonly canEditItems = computed(() => Boolean(this.list()?.id));
protected readonly showEditor = computed(() => this.isCreateMode() || this.editing());
protected readonly listForm = this.formBuilder.group({
name: ['', [Validators.required]],
@@ -66,6 +68,7 @@ export class ListDetailComponent implements OnInit {
if (this.isCreateMode()) {
this.loading.set(false);
this.editing.set(true);
this.listForm.reset({ name: '', description: '' });
return;
}
@@ -128,7 +131,10 @@ export class ListDetailComponent implements OnInit {
this.setList(list);
if (this.isCreateMode()) {
this.isCreateMode.set(false);
this.editing.set(false);
void this.router.navigate(['/lists', list.id], { replaceUrl: true });
} else {
this.editing.set(false);
}
this.snackBar.open('Liste gespeichert.', 'OK', { duration: 2500 });
},
@@ -196,6 +202,29 @@ export class ListDetailComponent implements OnInit {
});
}
protected startEditing(): void {
this.editing.set(true);
}
protected cancelEditing(): void {
const list = this.list();
if (this.isCreateMode()) {
void this.router.navigateByUrl('/lists');
return;
}
if (list) {
this.listForm.reset({
name: list.name,
description: list.description ?? '',
});
}
this.itemForm.reset({ title: '', required: true });
this.editing.set(false);
}
protected checkedCount(list: UserList): number {
return list.items.filter((item) => item.checked).length;
}