You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

144 lines
4.1 KiB

import { Component, inject, signal } from "@angular/core";
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
import { Router, RouterLink } from "@angular/router";
import { MATERIAL } from "../shared/material";
import { ApiService } from "../core/api.service";
@Component({
standalone: true,
imports: [ReactiveFormsModule, RouterLink, ...MATERIAL],
template: `<main class="login">
<mat-card
><mat-card-content
><div class="logo">A</div>
<h1>Willkommen zurück</h1>
<p class="muted">Ausbildungsstunden übersichtlich dokumentieren.</p>
<form [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field appearance="outline" class="full"
><mat-label>E-Mail</mat-label
><input
matInput
type="email"
formControlName="email"
autocomplete="email"
/><mat-icon matSuffix>mail</mat-icon><mat-hint></mat-hint></mat-form-field
><mat-form-field appearance="outline" class="full"
><mat-label>Passwort</mat-label
><input
matInput
type="password"
formControlName="password"
autocomplete="current-password"
/><mat-icon matSuffix>lock</mat-icon><mat-hint></mat-hint></mat-form-field
>
@if (error()) {
<p class="error">{{ error() }}</p>
}
<button
mat-flat-button
class="full"
[disabled]="form.invalid || loading()"
>
@if (loading()) {
<mat-spinner diameter="20" />
} @else {
Anmelden
}
</button>
<div class="auth-links">
<a routerLink="/forgot-password">Passwort vergessen?</a>
<a routerLink="/register">Konto registrieren</a>
</div>
<div class="legal"><a routerLink="/resend-confirmation">Bestätigungslink erneut senden</a></div>
<div class="legal"><a routerLink="/impressum">Impressum</a></div>
</form></mat-card-content
></mat-card
>
</main>`,
styles: [
`
.login {
min-height: 100%;
display: grid;
place-items: center;
padding: 20px;
background:
radial-gradient(circle at top left, #d9e9ff, transparent 45%), #f5f7fb;
}
.login mat-card {
width: min(430px, 100%);
padding: 24px;
border-radius: 24px !important;
}
.logo {
width: 54px;
height: 54px;
border-radius: 16px;
display: grid;
place-items: center;
background: #155bd7;
color: #fff;
font-size: 25px;
font-weight: 800;
}
h1 {
margin: 22px 0 6px;
}
.full {
margin-top: 10px;
}
.error {
color: #b3261e;
}
button.full {
height: 48px;
}
.auth-links {
display: flex;
justify-content: space-between;
gap: 16px;
margin-top: 20px;
}
.auth-links a {
color: #155bd7;
text-decoration: none;
font-weight: 500;
}
.legal {
text-align: center;
margin-top: 18px;
}
.legal a {
color: #687287;
text-decoration: none;
font-size: 13px;
}
`,
],
})
export class LoginComponent {
private readonly fb = inject(FormBuilder);
readonly loading = signal(false);
readonly error = signal("");
readonly form = this.fb.nonNullable.group({
email: ["", [Validators.required, Validators.email]],
password: ["", Validators.required],
});
constructor(
private api: ApiService,
private router: Router,
) {}
submit() {
if (this.form.invalid) return;
this.loading.set(true);
this.error.set("");
this.api
.login(this.form.value.email!, this.form.value.password!)
.subscribe({
next: () => this.router.navigate(["/dashboard"]),
error: (e) => {
this.loading.set(false);
this.error.set(e.error?.error || "Anmeldung fehlgeschlagen");
},
});
}
}