edit hinter button
This commit is contained in:
@@ -36,32 +36,44 @@
|
|||||||
<mat-card class="editor-card" appearance="outlined">
|
<mat-card class="editor-card" appearance="outlined">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>Details</mat-card-title>
|
<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-header>
|
||||||
|
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="listForm" class="list-form" (ngSubmit)="saveList()">
|
@if (showEditor()) {
|
||||||
<mat-form-field appearance="outline">
|
<form [formGroup]="listForm" class="list-form" (ngSubmit)="saveList()">
|
||||||
<mat-label>Titel</mat-label>
|
<mat-form-field appearance="outline">
|
||||||
<input matInput formControlName="name" autocomplete="off" />
|
<mat-label>Titel</mat-label>
|
||||||
@if (listForm.controls.name.hasError('required')) {
|
<input matInput formControlName="name" autocomplete="off" />
|
||||||
<mat-error>Titel ist erforderlich.</mat-error>
|
@if (listForm.controls.name.hasError('required')) {
|
||||||
}
|
<mat-error>Titel ist erforderlich.</mat-error>
|
||||||
</mat-form-field>
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="outline">
|
<mat-form-field appearance="outline">
|
||||||
<mat-label>Beschreibung</mat-label>
|
<mat-label>Beschreibung</mat-label>
|
||||||
<textarea matInput formControlName="description" rows="4"></textarea>
|
<textarea matInput formControlName="description" rows="4"></textarea>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<button mat-flat-button type="submit" [disabled]="saving()">
|
<button mat-flat-button type="submit" [disabled]="saving()">
|
||||||
@if (saving()) {
|
@if (saving()) {
|
||||||
<mat-progress-spinner mode="indeterminate" diameter="18" />
|
<mat-progress-spinner mode="indeterminate" diameter="18" />
|
||||||
} @else {
|
} @else {
|
||||||
<mat-icon aria-hidden="true">save</mat-icon>
|
<mat-icon aria-hidden="true">save</mat-icon>
|
||||||
}
|
}
|
||||||
{{ isCreateMode() ? 'Liste anlegen' : 'Speichern' }}
|
{{ isCreateMode() ? 'Liste anlegen' : 'Speichern' }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
} @else {
|
||||||
|
<div class="list-summary">
|
||||||
|
<p>{{ list()?.description || 'Keine Beschreibung hinterlegt.' }}</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
@@ -78,26 +90,28 @@
|
|||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
|
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="itemForm" class="item-form" (ngSubmit)="addItem()">
|
@if (showEditor()) {
|
||||||
<mat-form-field appearance="outline">
|
<form [formGroup]="itemForm" class="item-form" (ngSubmit)="addItem()">
|
||||||
<mat-label>Neues Item</mat-label>
|
<mat-form-field appearance="outline">
|
||||||
<input matInput formControlName="title" autocomplete="off" [disabled]="!canEditItems()" />
|
<mat-label>Neues Item</mat-label>
|
||||||
@if (itemForm.controls.title.hasError('required')) {
|
<input matInput formControlName="title" autocomplete="off" [disabled]="!canEditItems()" />
|
||||||
<mat-error>Item-Titel ist erforderlich.</mat-error>
|
@if (itemForm.controls.title.hasError('required')) {
|
||||||
}
|
<mat-error>Item-Titel ist erforderlich.</mat-error>
|
||||||
</mat-form-field>
|
}
|
||||||
|
</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()">
|
<button mat-flat-button type="submit" [disabled]="addingItem() || !canEditItems()">
|
||||||
@if (addingItem()) {
|
@if (addingItem()) {
|
||||||
<mat-progress-spinner mode="indeterminate" diameter="18" />
|
<mat-progress-spinner mode="indeterminate" diameter="18" />
|
||||||
} @else {
|
} @else {
|
||||||
<mat-icon aria-hidden="true">add</mat-icon>
|
<mat-icon aria-hidden="true">add</mat-icon>
|
||||||
}
|
}
|
||||||
Hinzufügen
|
Hinzufügen
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
@if (!canEditItems()) {
|
@if (!canEditItems()) {
|
||||||
<div class="inline-empty">
|
<div class="inline-empty">
|
||||||
@@ -143,7 +157,7 @@
|
|||||||
|
|
||||||
<a mat-button routerLink="/lists" class="secondary-back">
|
<a mat-button routerLink="/lists" class="secondary-back">
|
||||||
<mat-icon aria-hidden="true">arrow_back</mat-icon>
|
<mat-icon aria-hidden="true">arrow_back</mat-icon>
|
||||||
Zur Listenuebersicht
|
Zur Listenübersicht
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -34,6 +34,16 @@
|
|||||||
background: color-mix(in srgb, var(--mat-sys-surface-container-low) 94%, white);
|
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,
|
.list-form,
|
||||||
.item-form {
|
.item-form {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -72,6 +82,17 @@
|
|||||||
font-size: 48px;
|
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 {
|
.error-state mat-icon {
|
||||||
color: var(--mat-sys-error);
|
color: var(--mat-sys-error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,12 @@ export class ListDetailComponent implements OnInit {
|
|||||||
protected readonly isCreateMode = signal(false);
|
protected readonly isCreateMode = signal(false);
|
||||||
protected readonly loading = signal(true);
|
protected readonly loading = signal(true);
|
||||||
protected readonly saving = signal(false);
|
protected readonly saving = signal(false);
|
||||||
|
protected readonly editing = signal(false);
|
||||||
protected readonly addingItem = signal(false);
|
protected readonly addingItem = signal(false);
|
||||||
protected readonly errorMessage = signal<string | null>(null);
|
protected readonly errorMessage = signal<string | null>(null);
|
||||||
protected readonly updatingItemId = signal<string | null>(null);
|
protected readonly updatingItemId = signal<string | null>(null);
|
||||||
protected readonly canEditItems = computed(() => Boolean(this.list()?.id));
|
protected readonly canEditItems = computed(() => Boolean(this.list()?.id));
|
||||||
|
protected readonly showEditor = computed(() => this.isCreateMode() || this.editing());
|
||||||
|
|
||||||
protected readonly listForm = this.formBuilder.group({
|
protected readonly listForm = this.formBuilder.group({
|
||||||
name: ['', [Validators.required]],
|
name: ['', [Validators.required]],
|
||||||
@@ -66,6 +68,7 @@ export class ListDetailComponent implements OnInit {
|
|||||||
|
|
||||||
if (this.isCreateMode()) {
|
if (this.isCreateMode()) {
|
||||||
this.loading.set(false);
|
this.loading.set(false);
|
||||||
|
this.editing.set(true);
|
||||||
this.listForm.reset({ name: '', description: '' });
|
this.listForm.reset({ name: '', description: '' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -128,7 +131,10 @@ export class ListDetailComponent implements OnInit {
|
|||||||
this.setList(list);
|
this.setList(list);
|
||||||
if (this.isCreateMode()) {
|
if (this.isCreateMode()) {
|
||||||
this.isCreateMode.set(false);
|
this.isCreateMode.set(false);
|
||||||
|
this.editing.set(false);
|
||||||
void this.router.navigate(['/lists', list.id], { replaceUrl: true });
|
void this.router.navigate(['/lists', list.id], { replaceUrl: true });
|
||||||
|
} else {
|
||||||
|
this.editing.set(false);
|
||||||
}
|
}
|
||||||
this.snackBar.open('Liste gespeichert.', 'OK', { duration: 2500 });
|
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 {
|
protected checkedCount(list: UserList): number {
|
||||||
return list.items.filter((item) => item.checked).length;
|
return list.items.filter((item) => item.checked).length;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user