flare / flare-ui /src /app /components /login /login.component.ts
ciyidogan's picture
Upload 118 files
9f79da5 verified
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatIconModule } from '@angular/material/icon';
import { AuthService } from '../../services/auth.service';
@Component({
selector: 'app-login',
standalone: true,
imports: [
CommonModule,
FormsModule,
MatCardModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule,
MatProgressSpinnerModule,
MatIconModule
],
template: `
<div class="login-container">
<mat-card class="login-card">
<mat-card-header>
<mat-card-title>Flare Administration</mat-card-title>
</mat-card-header>
<mat-card-content>
<form (ngSubmit)="login()" #loginForm="ngForm">
<mat-form-field appearance="outline" class="full-width">
<mat-label>Username</mat-label>
<input
matInput
type="text"
name="username"
[(ngModel)]="username"
required
[disabled]="loading"
autocomplete="username"
>
<mat-icon matPrefix>person</mat-icon>
<mat-error>Username is required</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" class="full-width">
<mat-label>Password</mat-label>
<input
matInput
[type]="hidePassword ? 'password' : 'text'"
name="password"
[(ngModel)]="password"
required
[disabled]="loading"
autocomplete="current-password"
>
<mat-icon matPrefix>lock</mat-icon>
<button mat-icon-button matSuffix (click)="hidePassword = !hidePassword" type="button">
<mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
<mat-error>Password is required</mat-error>
</mat-form-field>
@if (error) {
<div class="error-message">
<mat-icon>error</mat-icon>
{{ error }}
</div>
}
<button
mat-raised-button
color="primary"
type="submit"
class="full-width submit-button"
[disabled]="loading || !loginForm.valid"
>
@if (loading) {
<mat-spinner diameter="20" class="button-spinner"></mat-spinner>
Logging in...
} @else {
<mat-icon>login</mat-icon>
Login
}
</button>
</form>
</mat-card-content>
</mat-card>
</div>
`,
styles: [`
.login-container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
}
.login-card {
width: 100%;
max-width: 400px;
padding: 20px;
mat-card-header {
display: flex;
justify-content: center;
margin-bottom: 30px;
mat-card-title {
font-size: 24px;
font-weight: 500;
color: #333;
}
}
}
.full-width {
width: 100%;
}
mat-form-field {
margin-bottom: 20px;
}
.error-message {
display: flex;
align-items: center;
gap: 8px;
color: #f44336;
font-size: 14px;
margin-bottom: 20px;
padding: 12px;
background-color: #ffebee;
border-radius: 4px;
mat-icon {
font-size: 20px;
width: 20px;
height: 20px;
}
}
.submit-button {
height: 48px;
font-size: 16px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
mat-icon {
margin-right: 4px;
}
}
.button-spinner {
display: inline-block;
margin-right: 8px;
}
::ng-deep {
.mat-mdc-card {
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.16) !important;
}
.mat-mdc-form-field-icon-prefix,
.mat-mdc-form-field-icon-suffix {
padding: 0 4px;
}
.mat-mdc-progress-spinner {
--mdc-circular-progress-active-indicator-color: white;
}
.mat-mdc-form-field-error {
font-size: 12px;
}
}
`]
})
export class LoginComponent {
private authService = inject(AuthService);
private router = inject(Router);
username = '';
password = '';
loading = false;
error = '';
hidePassword = true;
async login() {
this.loading = true;
this.error = '';
try {
await this.authService.login(this.username, this.password).toPromise();
this.router.navigate(['/']);
} catch (err: any) {
this.error = err.error?.detail || 'Invalid credentials';
} finally {
this.loading = false;
}
}
}