Onboarding

This commit is contained in:
Bastian Wagner
2026-06-09 13:07:07 +02:00
parent 537c7cbbee
commit 8f3806d398
29 changed files with 1037 additions and 26 deletions

View File

@@ -9,7 +9,13 @@
</div>
@if (canEditItems()) {
<div class="detail-actions">
<button mat-stroked-button type="button" [disabled]="copyingTemplate()" (click)="copyTemplateToList()">
<button
mat-stroked-button
type="button"
data-onboarding="template-copy"
[disabled]="copyingTemplate()"
(click)="copyTemplateToList()"
>
@if (copyingTemplate()) {
<mat-progress-spinner mode="indeterminate" diameter="18" />
} @else {
@@ -48,7 +54,7 @@
</mat-card-content>
</mat-card>
} @else {
<mat-card class="editor-card" appearance="outlined">
<mat-card class="editor-card" appearance="outlined" data-onboarding="template-details">
<mat-card-header>
<mat-card-title>Details</mat-card-title>
</mat-card-header>
@@ -80,7 +86,7 @@
</mat-card-content>
</mat-card>
<mat-card class="editor-card" appearance="outlined">
<mat-card class="editor-card" appearance="outlined" data-onboarding="template-item">
<mat-card-header>
<mat-card-title>Items</mat-card-title>
<mat-card-subtitle>

View File

@@ -13,6 +13,7 @@ import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { getAuthErrorMessage } from '../../auth/error-message';
import { OnboardingService } from '../../onboarding/onboarding.service';
import { ConfirmDeleteDialogComponent } from '../confirm-delete-dialog/confirm-delete-dialog.component';
import { ListTemplate } from '../templates.models';
import { TemplatesService } from '../templates.service';
@@ -43,6 +44,7 @@ export class TemplateDetailComponent implements OnInit {
private readonly router = inject(Router);
private readonly snackBar = inject(MatSnackBar);
private readonly templatesService = inject(TemplatesService);
protected readonly onboarding = inject(OnboardingService);
protected readonly template = signal<ListTemplate | null>(null);
protected readonly isCreateMode = signal(false);
@@ -104,6 +106,7 @@ export class TemplateDetailComponent implements OnInit {
protected saveTemplate(): void {
const templateId = this.templateId();
const creatingTemplate = this.isCreateMode() || !templateId;
if (this.templateForm.invalid) {
this.templateForm.markAllAsTouched();
@@ -127,11 +130,12 @@ export class TemplateDetailComponent implements OnInit {
.subscribe({
next: (template) => {
this.setTemplate(template);
if (this.isCreateMode()) {
if (creatingTemplate) {
this.isCreateMode.set(false);
void this.router.navigate(['/templates', template.id], {
replaceUrl: true,
});
this.onboarding.templateCreated(template.id);
}
this.snackBar.open('Template gespeichert.', 'OK', { duration: 2500 });
},
@@ -162,6 +166,7 @@ export class TemplateDetailComponent implements OnInit {
next: (template) => {
this.setTemplate(template);
this.itemForm.reset({ title: '', required: true });
this.onboarding.templateItemAdded();
},
error: (error: unknown) => {
this.snackBar.open(getAuthErrorMessage(error), 'OK', { duration: 5000 });
@@ -245,10 +250,11 @@ export class TemplateDetailComponent implements OnInit {
.createListFromTemplate(templateId)
.pipe(finalize(() => this.copyingTemplate.set(false)))
.subscribe({
next: () => {
next: (list) => {
this.snackBar.open('Liste aus Template erstellt.', 'OK', {
duration: 3000,
});
this.onboarding.templateCopiedToList(list.id);
void this.router.navigateByUrl('/lists');
},
error: (error: unknown) => {

View File

@@ -5,7 +5,12 @@
<p>Vorlagen fuer wiederkehrende Listen.</p>
</div>
<a mat-flat-button routerLink="/templates/new">
<a
mat-flat-button
routerLink="/templates/new"
data-onboarding="new-template"
(click)="onboarding.createTemplateClicked()"
>
<mat-icon aria-hidden="true">add</mat-icon>
Neues Template
</a>

View File

@@ -9,6 +9,7 @@ import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { getAuthErrorMessage } from '../auth/error-message';
import { OnboardingService } from '../onboarding/onboarding.service';
import { ConfirmDeleteDialogComponent } from './confirm-delete-dialog/confirm-delete-dialog.component';
import { ListTemplate, ListTemplateKind } from './templates.models';
import { TemplatesService } from './templates.service';
@@ -33,6 +34,7 @@ export class TemplatesComponent implements OnInit {
private readonly dialog = inject(MatDialog);
private readonly snackBar = inject(MatSnackBar);
private readonly templatesService = inject(TemplatesService);
protected readonly onboarding = inject(OnboardingService);
protected readonly templates = signal<ListTemplate[]>([]);
protected readonly loading = signal(true);