flare / flare-ui /src /app /components /user-info /user-info.component.ts
ciyidogan's picture
Upload 118 files
9f79da5 verified
import { Component, inject, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatCardModule } from '@angular/material/card';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { ApiService } from '../../services/api.service';
import { AuthService } from '../../services/auth.service';
import { Subject, takeUntil } from 'rxjs';
@Component({
selector: 'app-user-info',
standalone: true,
imports: [
CommonModule,
FormsModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule,
MatIconModule,
MatProgressBarModule,
MatCardModule,
MatSnackBarModule,
MatProgressSpinnerModule
],
templateUrl: './user-info.component.html',
styleUrls: ['./user-info.component.scss']
})
export class UserInfoComponent implements OnDestroy {
private apiService = inject(ApiService);
private authService = inject(AuthService);
private snackBar = inject(MatSnackBar);
private router = inject(Router);
username = this.authService.getUsername() || '';
currentPassword = '';
newPassword = '';
confirmPassword = '';
saving = false;
showCurrentPassword = false;
showNewPassword = false;
showConfirmPassword = false;
// Memory leak prevention
private destroyed$ = new Subject<void>();
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
get passwordStrength(): { level: number; text: string; color: string } {
if (!this.newPassword) {
return { level: 0, text: '', color: '' };
}
let strength = 0;
// Length check
if (this.newPassword.length >= 8) strength++;
if (this.newPassword.length >= 12) strength++;
// Character variety
if (/[a-z]/.test(this.newPassword)) strength++;
if (/[A-Z]/.test(this.newPassword)) strength++;
if (/[0-9]/.test(this.newPassword)) strength++;
if (/[^a-zA-Z0-9]/.test(this.newPassword)) strength++;
if (strength <= 2) {
return { level: 33, text: 'Weak', color: 'warn' };
} else if (strength <= 4) {
return { level: 66, text: 'Medium', color: 'accent' };
} else {
return { level: 100, text: 'Strong', color: 'primary' };
}
}
get isFormValid(): boolean {
return !!this.currentPassword &&
!!this.newPassword &&
this.newPassword === this.confirmPassword &&
this.newPassword.length >= 8;
}
changePassword() {
if (!this.isFormValid || this.saving) return;
this.saving = true;
this.apiService.changePassword(this.currentPassword, this.newPassword)
.pipe(takeUntil(this.destroyed$))
.subscribe({
next: () => {
this.saving = false;
// Clear form
this.currentPassword = '';
this.newPassword = '';
this.confirmPassword = '';
// Show success message
this.snackBar.open(
'Password changed successfully. Please login again.',
'OK',
{
duration: 5000,
panelClass: ['success-snackbar']
}
).afterDismissed().subscribe(() => {
// Logout after password change
this.authService.logout();
});
},
error: (error) => {
this.saving = false;
// Handle validation errors
if (error.status === 422 && error.error?.details) {
// Field-level errors
const fieldErrors = error.error.details;
if (fieldErrors.some((e: any) => e.field === 'current_password')) {
this.snackBar.open(
'Current password is incorrect',
'Close',
{
duration: 5000,
panelClass: ['error-snackbar']
}
);
} else if (fieldErrors.some((e: any) => e.field === 'new_password')) {
const pwError = fieldErrors.find((e: any) => e.field === 'new_password');
this.snackBar.open(
pwError.message || 'New password does not meet requirements',
'Close',
{
duration: 5000,
panelClass: ['error-snackbar']
}
);
}
} else {
// Generic error
this.snackBar.open(
error.error?.detail || 'Failed to change password',
'Close',
{
duration: 5000,
panelClass: ['error-snackbar']
}
);
}
}
});
}
togglePasswordVisibility(field: 'current' | 'new' | 'confirm') {
switch(field) {
case 'current':
this.showCurrentPassword = !this.showCurrentPassword;
break;
case 'new':
this.showNewPassword = !this.showNewPassword;
break;
case 'confirm':
this.showConfirmPassword = !this.showConfirmPassword;
break;
}
}
}