Spaces:
Running
Running
Update flare-ui/src/app/components/login/login.component.ts
Browse files
flare-ui/src/app/components/login/login.component.ts
CHANGED
@@ -7,6 +7,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
|
|
7 |
import { MatInputModule } from '@angular/material/input';
|
8 |
import { MatButtonModule } from '@angular/material/button';
|
9 |
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
|
10 |
import { AuthService } from '../../services/auth.service';
|
11 |
|
12 |
@Component({
|
@@ -19,51 +20,75 @@ import { AuthService } from '../../services/auth.service';
|
|
19 |
MatFormFieldModule,
|
20 |
MatInputModule,
|
21 |
MatButtonModule,
|
22 |
-
MatProgressSpinnerModule
|
|
|
23 |
],
|
24 |
template: `
|
25 |
<div class="login-container">
|
26 |
-
<
|
27 |
-
<
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}
|
64 |
-
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
</div>
|
68 |
`,
|
69 |
styles: [`
|
@@ -72,34 +97,89 @@ import { AuthService } from '../../services/auth.service';
|
|
72 |
display: flex;
|
73 |
align-items: center;
|
74 |
justify-content: center;
|
75 |
-
background
|
76 |
}
|
77 |
|
78 |
.login-card {
|
79 |
-
background: white;
|
80 |
-
padding: 2rem;
|
81 |
-
border-radius: 8px;
|
82 |
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
83 |
width: 100%;
|
84 |
max-width: 400px;
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
}
|
92 |
}
|
93 |
|
94 |
-
.
|
95 |
width: 100%;
|
96 |
}
|
97 |
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
display: flex;
|
100 |
align-items: center;
|
101 |
justify-content: center;
|
102 |
-
gap:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
}
|
104 |
`]
|
105 |
})
|
@@ -111,6 +191,7 @@ export class LoginComponent {
|
|
111 |
password = '';
|
112 |
loading = false;
|
113 |
error = '';
|
|
|
114 |
|
115 |
async login() {
|
116 |
this.loading = true;
|
|
|
7 |
import { MatInputModule } from '@angular/material/input';
|
8 |
import { MatButtonModule } from '@angular/material/button';
|
9 |
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
10 |
+
import { MatIconModule } from '@angular/material/icon';
|
11 |
import { AuthService } from '../../services/auth.service';
|
12 |
|
13 |
@Component({
|
|
|
20 |
MatFormFieldModule,
|
21 |
MatInputModule,
|
22 |
MatButtonModule,
|
23 |
+
MatProgressSpinnerModule,
|
24 |
+
MatIconModule
|
25 |
],
|
26 |
template: `
|
27 |
<div class="login-container">
|
28 |
+
<mat-card class="login-card">
|
29 |
+
<mat-card-header>
|
30 |
+
<mat-card-title>Flare Administration</mat-card-title>
|
31 |
+
</mat-card-header>
|
32 |
+
<mat-card-content>
|
33 |
+
<form (ngSubmit)="login()" #loginForm="ngForm">
|
34 |
+
<mat-form-field appearance="outline" class="full-width">
|
35 |
+
<mat-label>Username</mat-label>
|
36 |
+
<input
|
37 |
+
matInput
|
38 |
+
type="text"
|
39 |
+
name="username"
|
40 |
+
[(ngModel)]="username"
|
41 |
+
required
|
42 |
+
[disabled]="loading"
|
43 |
+
autocomplete="username"
|
44 |
+
>
|
45 |
+
<mat-icon matPrefix>person</mat-icon>
|
46 |
+
<mat-error>Username is required</mat-error>
|
47 |
+
</mat-form-field>
|
48 |
+
|
49 |
+
<mat-form-field appearance="outline" class="full-width">
|
50 |
+
<mat-label>Password</mat-label>
|
51 |
+
<input
|
52 |
+
matInput
|
53 |
+
[type]="hidePassword ? 'password' : 'text'"
|
54 |
+
name="password"
|
55 |
+
[(ngModel)]="password"
|
56 |
+
required
|
57 |
+
[disabled]="loading"
|
58 |
+
autocomplete="current-password"
|
59 |
+
>
|
60 |
+
<mat-icon matPrefix>lock</mat-icon>
|
61 |
+
<button mat-icon-button matSuffix (click)="hidePassword = !hidePassword" type="button">
|
62 |
+
<mat-icon>{{hidePassword ? 'visibility_off' : 'visibility'}}</mat-icon>
|
63 |
+
</button>
|
64 |
+
<mat-error>Password is required</mat-error>
|
65 |
+
</mat-form-field>
|
66 |
+
|
67 |
+
@if (error) {
|
68 |
+
<div class="error-message">
|
69 |
+
<mat-icon>error</mat-icon>
|
70 |
+
{{ error }}
|
71 |
+
</div>
|
72 |
}
|
73 |
+
|
74 |
+
<button
|
75 |
+
mat-raised-button
|
76 |
+
color="primary"
|
77 |
+
type="submit"
|
78 |
+
class="full-width submit-button"
|
79 |
+
[disabled]="loading || !loginForm.valid"
|
80 |
+
>
|
81 |
+
@if (loading) {
|
82 |
+
<mat-spinner diameter="20" class="button-spinner"></mat-spinner>
|
83 |
+
Logging in...
|
84 |
+
} @else {
|
85 |
+
<mat-icon>login</mat-icon>
|
86 |
+
Login
|
87 |
+
}
|
88 |
+
</button>
|
89 |
+
</form>
|
90 |
+
</mat-card-content>
|
91 |
+
</mat-card>
|
92 |
</div>
|
93 |
`,
|
94 |
styles: [`
|
|
|
97 |
display: flex;
|
98 |
align-items: center;
|
99 |
justify-content: center;
|
100 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
101 |
}
|
102 |
|
103 |
.login-card {
|
|
|
|
|
|
|
|
|
104 |
width: 100%;
|
105 |
max-width: 400px;
|
106 |
+
padding: 20px;
|
107 |
+
|
108 |
+
mat-card-header {
|
109 |
+
display: flex;
|
110 |
+
justify-content: center;
|
111 |
+
margin-bottom: 30px;
|
112 |
+
|
113 |
+
mat-card-title {
|
114 |
+
font-size: 24px;
|
115 |
+
font-weight: 500;
|
116 |
+
color: #333;
|
117 |
+
}
|
118 |
}
|
119 |
}
|
120 |
|
121 |
+
.full-width {
|
122 |
width: 100%;
|
123 |
}
|
124 |
|
125 |
+
mat-form-field {
|
126 |
+
margin-bottom: 20px;
|
127 |
+
}
|
128 |
+
|
129 |
+
.error-message {
|
130 |
+
display: flex;
|
131 |
+
align-items: center;
|
132 |
+
gap: 8px;
|
133 |
+
color: #f44336;
|
134 |
+
font-size: 14px;
|
135 |
+
margin-bottom: 20px;
|
136 |
+
padding: 12px;
|
137 |
+
background-color: #ffebee;
|
138 |
+
border-radius: 4px;
|
139 |
+
|
140 |
+
mat-icon {
|
141 |
+
font-size: 20px;
|
142 |
+
width: 20px;
|
143 |
+
height: 20px;
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
.submit-button {
|
148 |
+
height: 48px;
|
149 |
+
font-size: 16px;
|
150 |
+
margin-top: 10px;
|
151 |
display: flex;
|
152 |
align-items: center;
|
153 |
justify-content: center;
|
154 |
+
gap: 8px;
|
155 |
+
|
156 |
+
mat-icon {
|
157 |
+
margin-right: 4px;
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
.button-spinner {
|
162 |
+
display: inline-block;
|
163 |
+
margin-right: 8px;
|
164 |
+
}
|
165 |
+
|
166 |
+
::ng-deep {
|
167 |
+
.mat-mdc-card {
|
168 |
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.16) !important;
|
169 |
+
}
|
170 |
+
|
171 |
+
.mat-mdc-form-field-icon-prefix,
|
172 |
+
.mat-mdc-form-field-icon-suffix {
|
173 |
+
padding: 0 4px;
|
174 |
+
}
|
175 |
+
|
176 |
+
.mat-mdc-progress-spinner {
|
177 |
+
--mdc-circular-progress-active-indicator-color: white;
|
178 |
+
}
|
179 |
+
|
180 |
+
.mat-mdc-form-field-error {
|
181 |
+
font-size: 12px;
|
182 |
+
}
|
183 |
}
|
184 |
`]
|
185 |
})
|
|
|
191 |
password = '';
|
192 |
loading = false;
|
193 |
error = '';
|
194 |
+
hidePassword = true;
|
195 |
|
196 |
async login() {
|
197 |
this.loading = true;
|