ciyidogan commited on
Commit
5162e80
·
verified ·
1 Parent(s): 5343d65

Update flare-ui/src/app/components/user-info/user-info.component.ts

Browse files
flare-ui/src/app/components/user-info/user-info.component.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Component, inject } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
  import { FormsModule } from '@angular/forms';
4
  import { Router } from '@angular/router';
@@ -12,6 +12,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
12
  import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
13
  import { ApiService } from '../../services/api.service';
14
  import { AuthService } from '../../services/auth.service';
 
15
 
16
  @Component({
17
  selector: 'app-user-info',
@@ -31,7 +32,7 @@ import { AuthService } from '../../services/auth.service';
31
  templateUrl: './user-info.component.html',
32
  styleUrls: ['./user-info.component.scss']
33
  })
34
- export class UserInfoComponent {
35
  private apiService = inject(ApiService);
36
  private authService = inject(AuthService);
37
  private snackBar = inject(MatSnackBar);
@@ -45,6 +46,14 @@ export class UserInfoComponent {
45
  showCurrentPassword = false;
46
  showNewPassword = false;
47
  showConfirmPassword = false;
 
 
 
 
 
 
 
 
48
 
49
  get passwordStrength(): { level: number; text: string; color: string } {
50
  if (!this.newPassword) {
@@ -73,49 +82,94 @@ export class UserInfoComponent {
73
  }
74
 
75
  get isFormValid(): boolean {
76
- return !!(
77
- this.currentPassword &&
78
- this.newPassword &&
79
- this.confirmPassword &&
80
- this.newPassword === this.confirmPassword &&
81
- this.newPassword.length >= 8 &&
82
- /[a-z]/.test(this.newPassword) &&
83
- /[A-Z]/.test(this.newPassword) &&
84
- /[0-9]/.test(this.newPassword)
85
- );
86
  }
87
 
88
- async changePassword() {
89
- if (!this.isFormValid) {
90
- this.snackBar.open('Please fill all fields correctly', 'Close', { duration: 3000 });
91
- return;
92
- }
93
-
94
- if (this.newPassword !== this.confirmPassword) {
95
- this.snackBar.open('New passwords do not match', 'Close', { duration: 3000 });
96
- return;
97
- }
98
 
99
  this.saving = true;
100
- try {
101
- await this.apiService.changePassword(this.currentPassword, this.newPassword).toPromise();
102
- this.snackBar.open('Password changed successfully', 'Close', { duration: 3000 });
103
-
104
- // Clear form
105
- this.currentPassword = '';
106
- this.newPassword = '';
107
- this.confirmPassword = '';
108
-
109
- // Navigate to projects tab after successful password change
110
- setTimeout(() => {
111
- this.router.navigate(['/projects']);
112
- }, 500);
113
-
114
- } catch (error: any) {
115
- const message = error.error?.detail || 'Failed to change password';
116
- this.snackBar.open(message, 'Close', { duration: 5000 });
117
- } finally {
118
- this.saving = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
  }
121
  }
 
1
+ import { Component, inject, OnDestroy } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
  import { FormsModule } from '@angular/forms';
4
  import { Router } from '@angular/router';
 
12
  import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
13
  import { ApiService } from '../../services/api.service';
14
  import { AuthService } from '../../services/auth.service';
15
+ import { Subject, takeUntil } from 'rxjs';
16
 
17
  @Component({
18
  selector: 'app-user-info',
 
32
  templateUrl: './user-info.component.html',
33
  styleUrls: ['./user-info.component.scss']
34
  })
35
+ export class UserInfoComponent implements OnDestroy {
36
  private apiService = inject(ApiService);
37
  private authService = inject(AuthService);
38
  private snackBar = inject(MatSnackBar);
 
46
  showCurrentPassword = false;
47
  showNewPassword = false;
48
  showConfirmPassword = false;
49
+
50
+ // Memory leak prevention
51
+ private destroyed$ = new Subject<void>();
52
+
53
+ ngOnDestroy() {
54
+ this.destroyed$.next();
55
+ this.destroyed$.complete();
56
+ }
57
 
58
  get passwordStrength(): { level: number; text: string; color: string } {
59
  if (!this.newPassword) {
 
82
  }
83
 
84
  get isFormValid(): boolean {
85
+ return !!this.currentPassword &&
86
+ !!this.newPassword &&
87
+ this.newPassword === this.confirmPassword &&
88
+ this.newPassword.length >= 8;
 
 
 
 
 
 
89
  }
90
 
91
+ changePassword() {
92
+ if (!this.isFormValid || this.saving) return;
 
 
 
 
 
 
 
 
93
 
94
  this.saving = true;
95
+
96
+ this.apiService.changePassword(this.currentPassword, this.newPassword)
97
+ .pipe(takeUntil(this.destroyed$))
98
+ .subscribe({
99
+ next: () => {
100
+ this.saving = false;
101
+
102
+ // Clear form
103
+ this.currentPassword = '';
104
+ this.newPassword = '';
105
+ this.confirmPassword = '';
106
+
107
+ // Show success message
108
+ this.snackBar.open(
109
+ 'Password changed successfully. Please login again.',
110
+ 'OK',
111
+ {
112
+ duration: 5000,
113
+ panelClass: ['success-snackbar']
114
+ }
115
+ ).afterDismissed().subscribe(() => {
116
+ // Logout after password change
117
+ this.authService.logout();
118
+ });
119
+ },
120
+ error: (error) => {
121
+ this.saving = false;
122
+
123
+ // Handle validation errors
124
+ if (error.status === 422 && error.error?.details) {
125
+ // Field-level errors
126
+ const fieldErrors = error.error.details;
127
+ if (fieldErrors.some((e: any) => e.field === 'current_password')) {
128
+ this.snackBar.open(
129
+ 'Current password is incorrect',
130
+ 'Close',
131
+ {
132
+ duration: 5000,
133
+ panelClass: ['error-snackbar']
134
+ }
135
+ );
136
+ } else if (fieldErrors.some((e: any) => e.field === 'new_password')) {
137
+ const pwError = fieldErrors.find((e: any) => e.field === 'new_password');
138
+ this.snackBar.open(
139
+ pwError.message || 'New password does not meet requirements',
140
+ 'Close',
141
+ {
142
+ duration: 5000,
143
+ panelClass: ['error-snackbar']
144
+ }
145
+ );
146
+ }
147
+ } else {
148
+ // Generic error
149
+ this.snackBar.open(
150
+ error.error?.detail || 'Failed to change password',
151
+ 'Close',
152
+ {
153
+ duration: 5000,
154
+ panelClass: ['error-snackbar']
155
+ }
156
+ );
157
+ }
158
+ }
159
+ });
160
+ }
161
+
162
+ togglePasswordVisibility(field: 'current' | 'new' | 'confirm') {
163
+ switch(field) {
164
+ case 'current':
165
+ this.showCurrentPassword = !this.showCurrentPassword;
166
+ break;
167
+ case 'new':
168
+ this.showNewPassword = !this.showNewPassword;
169
+ break;
170
+ case 'confirm':
171
+ this.showConfirmPassword = !this.showConfirmPassword;
172
+ break;
173
  }
174
  }
175
  }