Skip to content

Commit

Permalink
feat(user): Recover and reset pass added
Browse files Browse the repository at this point in the history
* fix(login): fix recover pass (get email) page

* feat(login): reset pass component added

* fix(test): fix new components test
  • Loading branch information
asAlwaysZahra authored Sep 9, 2024
1 parent 8e62546 commit fa866e3
Show file tree
Hide file tree
Showing 12 changed files with 444 additions and 67 deletions.
4 changes: 2 additions & 2 deletions api-config/api-url.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const environment = {
// apiUrl: 'https://localhost:44322',
apiUrl: 'http://localhost:8085',
apiUrl: 'https://localhost:44322',
// apiUrl: 'http://localhost:8085',
};
6 changes: 6 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { AssignFileComponent } from './user/components/dashboard/assign-file/ass
import { CategoryComponent } from './graph/components/category/category.component';
import { RecoverPassFormComponent } from './user/components/login/recover-pass-form/recover-pass-form.component';
import { LoginFormComponent } from './user/components/login/login-form/login-form.component';
import { ResetPasswordComponent } from './user/components/login/reset-password/reset-password.component';

const routes: Routes = [
{
Expand Down Expand Up @@ -84,6 +85,11 @@ const routes: Routes = [
},
],
},
{
path: 'reset-password',
component: ResetPasswordComponent,
title: 'StarData | Reset Password',
},
{
path: '',
component: AppComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,24 @@
<h2 class="logo-text">StarData</h2>
</div>
<h2>Recover Password</h2>
<p class="sub-title">
Enter your email address and we will send you a link to reset your password.
</p>
<form>
<mat-form-field appearance="fill" class="form-field">
<mat-label>Recovery Email</mat-label>
<input
[(ngModel)]="recover_email"
matInput
name="email"
disabled="{{ isTrueRecoverCode }}"
/>
<input [(ngModel)]="recover_email" matInput name="email" />
</mat-form-field>
@if (isTrueRecoverCode) {
<mat-form-field class="form-field">
<mat-label>New Password</mat-label>
<input
placeholder="at least 8 chracters"
[(ngModel)]="password"
matInput
[type]="hide() ? 'password' : 'text'"
name="password"
/>
<button
mat-icon-button
matSuffix
(click)="hidePassClick($event)"
[attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hide()"
type="button"
>
<mat-icon>{{ hide() ? "visibility_off" : "visibility" }}</mat-icon>
</button>
</mat-form-field>
}
<button
type="button"
mat-flat-button
[disabled]="isLoading"
(click)="isTrueRecoverCode ? recoverClick($event) : sendCodeClick($event)"
(click)="recoverClick($event)"
>
@if (isLoading) {
Processing...
} @else {
@if (isTrueRecoverCode) {
Recover
} @else {
Send Code
}
Send Email
}
</button>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';

describe('RecoverPassFormComponent', () => {
let component: RecoverPassFormComponent;
Expand All @@ -25,6 +27,7 @@ describe('RecoverPassFormComponent', () => {
MatButtonModule,
BrowserAnimationsModule,
],
providers: [provideHttpClient(), provideHttpClientTesting()],
}).compileComponents();

fixture = TestBed.createComponent(RecoverPassFormComponent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,51 @@
import { Component, signal } from '@angular/core';
import { Component } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { LoadingService } from '../../../../shared/services/loading.service';
import { UserService } from '../../../services/user/user.service';
import { DangerSuccessNotificationComponent } from '../../../../shared/components/danger-success-notification/danger-success-notification.component';
import { Router } from '@angular/router';

@Component({
selector: 'app-recover-pass-form',
templateUrl: './recover-pass-form.component.html',
styleUrl: './recover-pass-form.component.scss',
})
export class RecoverPassFormComponent {
hide = signal(true);
username = '';
password = '';
isLoading = false;
recover_email = '';
isTrueRecoverCode = false;

constructor(
private _snackBar: MatSnackBar,
private loadingService: LoadingService,
private userService: UserService,
private router: Router,
) {
this.loadingService.setLoading(false);
}

recoverClick(event: Event) {
event.preventDefault();
console.log(1);
}

sendCodeClick(event: Event) {
event.preventDefault();
console.log(2);
this.isTrueRecoverCode = true;
}

hidePassClick(event: MouseEvent) {
this.hide.set(!this.hide());
event.stopPropagation();
this.isLoading = true;
this.userService.requestResetPassword(this.recover_email).subscribe({
next: () => {
this._snackBar.openFromComponent(DangerSuccessNotificationComponent, {
data: 'Password reset link sent to your email.\nPlease check your email.',
panelClass: ['notification-class-success'],
duration: 5000,
});
this.router.navigate(['/login']);
this.loadingService.setLoading(false);
this.isLoading = false;
},
error: (error) => {
this._snackBar.openFromComponent(DangerSuccessNotificationComponent, {
data: error.error.message,
panelClass: ['notification-class-danger'],
duration: 2000,
});
this.loadingService.setLoading(false);
this.isLoading = false;
},
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<div class="container">
<div class="login-container">
<div class="form-container">
<div class="logo">
<img src="logo.png" alt="logo" class="logo-image" />
<h2 class="logo-text">StarData</h2>
</div>
<h2>Reset Password</h2>
<p>Enter your new password. Your password should be:</p>
<form>
<mat-form-field class="form-field">
<mat-label>New Password</mat-label>
<input
placeholder="at least 8 chracters"
[(ngModel)]="password"
matInput
[type]="hide() ? 'password' : 'text'"
name="password"
/>
<button
mat-icon-button
matSuffix
(click)="hidePassClick($event)"
[attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hide()"
type="button"
>
<mat-icon>{{ hide() ? "visibility_off" : "visibility" }}</mat-icon>
</button>
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>Confirm Password</mat-label>
<input
placeholder="please repeat your password"
[(ngModel)]="confirmPassword"
matInput
[type]="hide() ? 'password' : 'text'"
name="password"
/>
<button
mat-icon-button
matSuffix
(click)="hidePassClick($event)"
[attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hide()"
type="button"
>
<mat-icon>{{ hide() ? "visibility_off" : "visibility" }}</mat-icon>
</button>
</mat-form-field>
<app-card>
<ul>
<li>At least 8 characters</li>
<li>Contain at least one uppercase letter (A-Z)</li>
<li>Contain at least one lowercase letter (a-z)</li>
<li>Contain at least one number (0-9)</li>
<li>Contain at least one special character (&#64;$!%*?&)</li>
</ul>
</app-card>
<button
type="button"
mat-flat-button
[disabled]="isLoading"
(click)="resetClick()"
>
@if (isLoading) {
Processing...
} @else {
Reset Password
}
</button>
</form>
</div>
</div>
<div class="vertical-line"></div>
<div #network id="network"></div>
<button (click)="changeTheme()" mat-fab class="theme-changer-container">
<mat-icon class="icon material-symbols-outlined" id="theme-changer-icon">
routine
</mat-icon>
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.container {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: var(--mat-app-background-color);
color: var(--mat-sidenav-content-text-color);
gap: 1rem;

.form-container {
display: flex;
justify-content: flex-start;
flex-direction: column;
gap: 1rem;
width: 35rem;

.logo {
display: flex;
align-items: center;
gap: 0.5rem;

.logo-text {
font-size: 1.6rem;
margin: 0;
}

.logo-image {
height: 45px;
filter: var(--logo-filter);
}
}

> h2 {
font-weight: 600;
font-size: 2rem;
}

form {
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
width: 100%;

.form-field {
width: 100%;
}

> button {
font-size: 1rem;
width: 100%;
height: 3.3rem;
border-radius: 4rem;
margin-block: 1.6rem;
}

> .forget {
display: flex;
gap: 0.4rem;
font-size: 0.8rem;

.recover {
text-decoration: none;
color: var(--mdc-filled-button-container-color);
font-weight: 550;
cursor: pointer;
position: relative;

&::after {
content: "";
position: absolute;
width: 100%;
transform: scaleX(0);
height: 1px;
bottom: 0;
left: 0;
background-color: var(--mdc-filled-button-container-color);
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}

&:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
}
}
}
}
}

.login-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;

ul {
list-style-type: disc;
}
}

.vertical-line {
height: 600px;
//border-left: 1px solid var(--mat-sidenav-content-text-color);
}

#network {
height: 100%;
width: 100%;
}

.theme-changer-container {
position: fixed;
bottom: 3rem;
left: 3rem;
}
}
Loading

0 comments on commit fa866e3

Please sign in to comment.