diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 5440a2ce75fb961d07b90e24f08bef47b852f93f..3a3dbab52295156bc4438f638f87bd2b2792b22d 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -11,9 +11,8 @@ import { LoginComponent } from './login/login.component'; import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component'; import { PageComponent } from './page/page.component'; import { ResetEmailComponent } from './reset-email/reset-email.component'; -import { ResetPasswordComponent } from './reset-password/reset-password.component'; +import { ForgotPasswordComponent } from './reset-password/forgot-password.component'; import { StructureResolver } from './resolvers/structure.resolver'; -import { PasswordFormComponent } from './shared/components'; import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component'; import { StructureListSearchPrintComponent } from './structure-list/components/structure-list-search-print/structure-list-search-print.component'; import { StructureListComponent } from './structure-list/structure-list.component'; @@ -183,15 +182,10 @@ const routes: Routes = [ children: [ { path: '', - component: ResetPasswordComponent, + component: ForgotPasswordComponent, }, - footerOutletRoute, ], }, - { - path: 'new-password', - component: PasswordFormComponent, - }, { path: 'newsletter', title: buildTitle('Newsletter'), diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e993320287f5c3c4a08631125806df52cc7ff148..50eba291c77fb069bf1b169c152f7d16a1659977 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -31,6 +31,7 @@ import { MapModule } from './map/map.module'; import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component'; import { PageComponent } from './page/page.component'; import { ResetEmailComponent } from './reset-email/reset-email.component'; +import { ForgotPasswordComponent } from './reset-password/forgot-password.component'; import { ResetPasswordComponent } from './reset-password/reset-password.component'; import { PersonalOfferResolver } from './resolvers/personal-offer.resolver'; import { StructureResolver } from './resolvers/structure.resolver'; @@ -53,6 +54,7 @@ import { StructureJoinComponent } from './structure/structure-join/structure-joi PageComponent, ContactComponent, ResetEmailComponent, + ForgotPasswordComponent, ResetPasswordComponent, StructureJoinComponent, NewsletterSubscriptionComponent, diff --git a/src/app/form/form-view/account-form/account-credentials/account-credentials.component.html b/src/app/form/form-view/account-form/account-credentials/account-credentials.component.html index 6c6ae7d94ec728adb3a7f7f1549f0eed3eeab8c8..b6d82a73c94b496c8383903ce65b23ab49138476 100644 --- a/src/app/form/form-view/account-form/account-credentials/account-credentials.component.html +++ b/src/app/form/form-view/account-form/account-credentials/account-credentials.component.html @@ -10,7 +10,7 @@ autocomplete="on" size="large" [disabled]="isAccountMode" - [status]="accountForm.get('email').value ? (accountForm.get('email').invalid ? 'error' : 'success') : null" + [status]="getStatus(accountForm.get('email'))" [statusText]="accountForm.get('email').hasError('alreadyExist') ? 'Cet email est déjà utilisé' : null" [value]="accountForm.get('email').value" (valueChange)="accountForm.get('email').setValue($event); setValidationsForm(); verifyUserExist($event)" diff --git a/src/app/reset-password/forgot-password.component.html b/src/app/reset-password/forgot-password.component.html new file mode 100644 index 0000000000000000000000000000000000000000..8d603b0aa8e51f52bd4bbe6965aa3c3e22e5c58c --- /dev/null +++ b/src/app/reset-password/forgot-password.component.html @@ -0,0 +1,27 @@ +<div *ngIf="!token" class="resetPage"> + <div class="title"> + <h1>Mot de passe oublié</h1> + <p>Saisissez votre email afin de réinitialiser votre mot de passe</p> + </div> + <form [formGroup]="forgotPasswordForm" (ngSubmit)="onSubmit()"> + <app-input + size="large" + [placeholder]="'exemple@mail.com'" + [label]="'Email du compte'" + [value]="email.value" + [status]="email.value ? (email.invalid ? 'error' : 'success') : null" + (valueChange)="email.setValue($event)" + /> + + <div class="footer"> + <app-button [variant]="'secondary'" [label]="'Annuler'" (action)="goLogin()" /> + <app-button + [variant]="'primary'" + [label]="'Envoyer'" + [type]="'submit'" + [disabled]="loading || forgotPasswordForm.invalid" + /> + </div> + </form> +</div> +<app-password-form *ngIf="token" [token]="token" /> diff --git a/src/app/reset-password/forgot-password.component.ts b/src/app/reset-password/forgot-password.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..81fd6e5d9123eec050411a33eba3f4f0c810cfeb --- /dev/null +++ b/src/app/reset-password/forgot-password.component.ts @@ -0,0 +1,59 @@ +import { Component, OnInit } from '@angular/core'; +import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { AuthService } from '../services/auth.service'; +import { NotificationService } from '../services/notification.service'; +import { CustomRegExp } from '../utils/CustomRegExp'; + +@Component({ + selector: 'app-reset-password', + templateUrl: './forgot-password.component.html', + styleUrls: ['./reset-password.component.scss'], +}) +export class ForgotPasswordComponent implements OnInit { + public forgotPasswordForm = new FormGroup({ + email: new FormControl('', [Validators.required, Validators.pattern(CustomRegExp.EMAIL)]), + }); + public loading = false; + public token: string; + + constructor( + private authService: AuthService, + private router: Router, + private notificationService: NotificationService, + private activatedRoute: ActivatedRoute, + ) {} + + ngOnInit(): void { + this.activatedRoute.queryParams.subscribe((params) => { + this.token = params.token; + }); + } + + /** Getter for email control */ + get email(): AbstractControl<string, string> { + return this.forgotPasswordForm.get('email'); + } + + public onSubmit(): void { + // stop here if form is invalid + if (this.forgotPasswordForm.invalid) return; + + this.loading = true; + this.authService.resetPassword(this.email.value).subscribe({ + next: () => { + this.notificationService.showSuccess( + 'Un mail de confirmation de modification de votre mot de passe vous a été envoyé.', + ); + this.goLogin(); + }, + complete: () => { + this.loading = false; + }, + }); + } + + public goLogin(): void { + this.router.navigateByUrl('/login'); + } +} diff --git a/src/app/reset-password/reset-password.component.html b/src/app/reset-password/reset-password.component.html index de0851ff66bf9ad21153442de2095ee31d55a6a0..b8c8599822896cba70c2fa0e018c5d633ae7ea5f 100644 --- a/src/app/reset-password/reset-password.component.html +++ b/src/app/reset-password/reset-password.component.html @@ -1,32 +1,80 @@ -<div *ngIf="!token" class="resetPage"> - <div class="resetPasswordForm"> - <div class="title"> - <h1>Mot de passe oublié</h1> - <p>Saisissez votre email afin de réinitialiser votre mot de passe</p> - </div> +<div class="resetPage"> + <div class="title"> + <h1>Réinitialisation du mot de passe</h1> + </div> + <form [formGroup]="resetPasswordForm" (ngSubmit)="onSubmit()"> <div class="fields"> - <form [formGroup]="resetForm" (ngSubmit)="onSubmit()"> - <div class="form-group"> - <label for="email">Email du compte</label> - <div fxLayout="row" fxLayoutGap="13px"> - <input - type="text" - autocomplete="on" - formControlName="email" - class="form-input" - [ngClass]="{ inputInvalid: submitted && f.email.errors }" + <app-input + id="password" + label="Création du mot de passe" + size="large" + type="password" + [value]="password.value" + (valueChange)="password.setValue($event)" + /> + <div class="passwordConditions"> + <p>Le mot de passe doit obligatoirement contenir :</p> + <ul> + <li [ngClass]="checkIfPasswordHasEnoughChar(password.value) ? 'valid' : 'invalid'"> + <app-svg-icon + [iconClass]="'icon-16'" + [folder]="'form'" + [icon]="checkIfPasswordHasEnoughChar(password.value) ? 'validate' : 'notValidate'" + /> + <p>8 caractères</p> + </li> + <li [ngClass]="checkIfPasswordHasSpecialChar(password.value) ? 'valid' : 'invalid'"> + <app-svg-icon + [iconClass]="'icon-16'" + [folder]="'form'" + [icon]="checkIfPasswordHasSpecialChar(password.value) ? 'validate' : 'notValidate'" + /> + <p>1 caractère spécial</p> + </li> + <li [ngClass]="checkIfPasswordHasLowerCase(password.value) ? 'valid' : 'invalid'"> + <app-svg-icon + [iconClass]="'icon-16'" + [folder]="'form'" + [icon]="checkIfPasswordHasLowerCase(password.value) ? 'validate' : 'notValidate'" /> - </div> - <div *ngIf="submitted && f.email.errors" class="incorrectId"> - <div *ngIf="f.email.errors.required">L'adresse e-mail est requise</div> - </div> - </div> - <div class="footer" fxLayout="row" fxLayoutAlign="space-between center"> - <app-button [variant]="'secondary'" [label]="'Annuler'" (action)="goLogin()" /> - <app-button [variant]="'primary'" [label]="'Envoyer'" [type]="'submit'" [disabled]="loading" /> - </div> - </form> + <p>1 caractère en minuscule</p> + </li> + <li [ngClass]="checkIfPasswordHasUpperCase(password.value) ? 'valid' : 'invalid'"> + <app-svg-icon + [iconClass]="'icon-16'" + [folder]="'form'" + [icon]="checkIfPasswordHasUpperCase(password.value) ? 'validate' : 'notValidate'" + /> + <p>1 caractère en majuscule</p> + </li> + <li [ngClass]="checkIfPasswordHasDigit(password.value) ? 'valid' : 'invalid'"> + <app-svg-icon + [iconClass]="'icon-16'" + [folder]="'form'" + [icon]="checkIfPasswordHasDigit(password.value) ? 'validate' : 'notValidate'" + /> + <p>1 chiffre</p> + </li> + </ul> + </div> + + <app-input + id="confirmPassword" + label="Vérification du mot de passe" + size="large" + type="password" + [status]="confirmPassword.value ? (confirmPassword.invalid ? 'error' : 'success') : null" + [value]="confirmPassword.value" + (valueChange)="confirmPassword.setValue($event)" + /> </div> - </div> + <div class="footer"> + <app-button + [variant]="'primary'" + [label]="'Confirmer'" + [type]="'submit'" + [disabled]="loading || resetPasswordForm.invalid" + /> + </div> + </form> </div> -<app-password-form *ngIf="token" /> diff --git a/src/app/reset-password/reset-password.component.scss b/src/app/reset-password/reset-password.component.scss index 5d883e7a54b4dfecff07da97e64889b58e0c17dd..099a767f74f818cb053a2ef7276cf0c2d01d5a90 100644 --- a/src/app/reset-password/reset-password.component.scss +++ b/src/app/reset-password/reset-password.component.scss @@ -1,64 +1,77 @@ @import 'color'; @import 'typography'; @import 'breakpoint'; -@import 'layout'; + +:host { + height: 100%; +} .resetPage { + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + height: 100%; width: 100%; max-width: 980px; box-sizing: border-box; margin: auto; - margin-top: 2rem; - min-height: 450px; - max-height: 75vh; - overflow-y: auto; - background: $white; - border-radius: 8px; - border: 1px solid $grey-6; - padding: 32px 24px 32px 48px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.resetPasswordForm { - display: flex; - flex-direction: column; - align-items: center; - h1, - p { - text-align: center; - margin: 0.5rem 0; - } - h1 { - @include font-bold-24; - } - p { - @include font-regular-14; - } -} -.form-group { - max-width: 320px; - margin-top: 2rem; + padding: 96px 48px 40px 48px; + gap: 40px; - label { - color: $grey-2; - } - .button { - margin-top: 20px; + @media #{$phone} { + padding: 32px 16px 32px 16px; } - .form-input { - width: 320px; - } - .inputInvalid { - border-color: $orange-warning; + + .title { + display: flex; + flex-direction: column; + gap: 16px; + text-align: center; + + h1 { + @include font-bold-24; + } + p { + @include font-regular-18; + } } - .incorrectId { - @include font-regular-14; - color: $orange-warning; + + form { + display: flex; + flex-direction: column; + justify-content: space-between; + height: 100%; + + .fields { + display: flex; + flex-direction: column; + gap: 16px; + + .passwordConditions { + ul { + padding-left: 12px; + margin: 0.5rem 0; + } + + li { + display: flex; + align-items: center; + color: $red-error; + gap: 8px; + &.valid { + color: $info-success; + } + } + } + } + .footer { + display: flex; + justify-content: center; + margin-top: 16px; + padding-top: 32px; + border-top: 1px solid $grey-6; + gap: 32px; + } } } -.footer { - width: 340px; - margin-top: 2rem; -} diff --git a/src/app/reset-password/reset-password.component.ts b/src/app/reset-password/reset-password.component.ts index 74e59d44515267a741561c9909642f8b07b738a4..0afa8a50d4cb0201c502f72ebe7f5ec8ecabe208 100644 --- a/src/app/reset-password/reset-password.component.ts +++ b/src/app/reset-password/reset-password.component.ts @@ -1,65 +1,96 @@ -import { Component, OnInit } from '@angular/core'; -import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; -import { ActivatedRoute, Router } from '@angular/router'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Component, Input } from '@angular/core'; +import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms'; +import { Router } from '@angular/router'; import { AuthService } from '../services/auth.service'; import { NotificationService } from '../services/notification.service'; +import { MustMatch } from '../shared/validator/form'; +import { CustomRegExp } from '../utils/CustomRegExp'; @Component({ - selector: 'app-reset-password', + selector: 'app-password-form', templateUrl: './reset-password.component.html', styleUrls: ['./reset-password.component.scss'], }) -export class ResetPasswordComponent implements OnInit { - public resetForm: UntypedFormGroup; - public loading = false; - public submitted = false; - public token: string; +export class ResetPasswordComponent { + @Input({ required: true }) token: string; + + public resetPasswordForm = new FormGroup( + { + password: new FormControl('', [Validators.required, Validators.pattern(CustomRegExp.PASSWORD)]), + confirmPassword: new FormControl('', [Validators.required, Validators.pattern(CustomRegExp.PASSWORD)]), + }, + { validators: MustMatch('password', 'confirmPassword') }, + ); + public loading: boolean; constructor( - private formBuilder: UntypedFormBuilder, - private authService: AuthService, private router: Router, + private authService: AuthService, private notificationService: NotificationService, - private activatedRoute: ActivatedRoute, ) {} - ngOnInit(): void { - this.activatedRoute.queryParams.subscribe((params) => { - this.token = params.token; - }); - this.resetForm = this.formBuilder.group({ - email: ['', Validators.required], - }); + /** Getter for password control */ + get password(): AbstractControl<string, string> { + return this.resetPasswordForm.get('password'); } - // getter for form fields - get f(): Record<string, AbstractControl> { - return this.resetForm.controls; + /** Getter for confirmPassword control */ + get confirmPassword(): AbstractControl<string, string> { + return this.resetPasswordForm.get('confirmPassword'); } - public onSubmit(): void { - this.submitted = true; + public checkIfPasswordHasEnoughChar(password: string): boolean { + return password.length >= 8; + } + + public checkIfPasswordHasSpecialChar(password: string): boolean { + return Boolean(RegExp(CustomRegExp.SPECHAR).exec(password)); + } + + public checkIfPasswordHasDigit(password: string): boolean { + return Boolean(RegExp(CustomRegExp.DIGIT).exec(password)); + } + public checkIfPasswordHasUpperCase(password: string): boolean { + return Boolean(RegExp(CustomRegExp.UPPERCASE).exec(password)); + } + + public checkIfPasswordHasLowerCase(password: string): boolean { + return Boolean(RegExp(CustomRegExp.LOWERCASE).exec(password)); + } + + public passwordIsValid(password: string): boolean { + return ( + this.checkIfPasswordHasEnoughChar(password) && + this.checkIfPasswordHasSpecialChar(password) && + this.checkIfPasswordHasDigit(password) && + this.checkIfPasswordHasUpperCase(password) && + this.checkIfPasswordHasLowerCase(password) + ); + } + + public onSubmit(): void { // stop here if form is invalid - if (this.resetForm.invalid) { - return; - } + if (this.resetPasswordForm.invalid) return; this.loading = true; - this.authService.resetPassword(this.f.email.value).subscribe({ + this.authService.resetPasswordApply(this.token, this.resetPasswordForm.value.password).subscribe({ next: () => { - this.notificationService.showSuccess( - 'Un mail de confirmation de modification de votre mot de passe vous a été envoyé.', - ); - this.router.navigate(['/login']); + this.notificationService.showSuccess('Votre mot de passe a été réinitialisé avec succès.'); + }, + error: (error: HttpErrorResponse) => { + this.loading = false; + if (error.status === 401) { + this.notificationService.showError('Lien de réinitialisation de mot de passe invalide'); + } else { + this.notificationService.showError('Échec de la réinitialisation de votre mot de passe'); + } }, complete: () => { this.loading = false; + this.router.navigate(['']); }, }); } - - public goLogin(): void { - this.router.navigateByUrl('/login'); - } } diff --git a/src/app/shared/components/index.ts b/src/app/shared/components/index.ts index f268adefd3f19225df00002fa5d8a074cf68e20b..33c912dd828c2f55731b2d56bad6a4fd5a5c1ca2 100644 --- a/src/app/shared/components/index.ts +++ b/src/app/shared/components/index.ts @@ -20,7 +20,6 @@ import { InputComponent } from './input/input.component'; import { LogoCardComponent } from './logo-card/logo-card.component'; import { MemberCardComponent } from './member-card/member-card.component'; import { ModalComponent } from './modal/modal.component'; -import { PasswordFormComponent } from './password-form/password-form.component'; import { RadioOptionComponent } from './radio-option/radio-option.component'; import { RadioComponent } from './radio/radio.component'; import { SearchBarComponent } from './search-bar/search-bar.component'; @@ -50,7 +49,6 @@ export { LogoCardComponent, MemberCardComponent, ModalComponent, - PasswordFormComponent, ProgressBarComponent, RadioOptionComponent, StructureDetailPrintComponent, @@ -85,7 +83,6 @@ export const SharedComponents = [ MemberCardComponent, LogoCardComponent, ModalComponent, - PasswordFormComponent, ProgressBarComponent, RadioOptionComponent, RadioComponent, diff --git a/src/app/shared/components/password-form/password-form.component.html b/src/app/shared/components/password-form/password-form.component.html deleted file mode 100644 index 4e19f2a51456e5984cfa17eb063d5bed2f369eca..0000000000000000000000000000000000000000 --- a/src/app/shared/components/password-form/password-form.component.html +++ /dev/null @@ -1,211 +0,0 @@ -<div class="content"> - <div class="resetPage"> - <h1>Réinitialisation du mot de passe</h1> - <form [formGroup]="accountForm" (ngSubmit)="onSubmitPassword()"> - <div *ngIf="oldPasswordNeeded" class="form-group" fxLayout="column"> - <label for="oldPassword">Ancien mot de passe</label> - <div fxLayout="row" fxLayoutGap="13px"> - <input - formControlName="oldPassword" - class="form-input password" - autocomplete="on" - [type]="isShowOldPassword ? 'text' : 'password'" - /> - <app-svg-icon - tabindex="0" - [folder]="'form'" - [iconClass]="'grey'" - [icon]="'visibility'" - (click)="showOldPassword()" - (keyup.enter)="showOldPassword()" - /> - <app-svg-icon - *ngIf="!checkOldPassword(accountForm.value.oldPassword)" - [folder]="'form'" - [icon]="'notValidate'" - /> - </div> - <p *ngIf="passwordError" class="special invalid">Votre ancien mot de passe est incorrect.</p> - </div> - <div class="form-group" fxLayout="column"> - <label for="password"> Le mot de passe doit contenir au minimum :</label> - <ul> - <li - class="" - [ngClass]="{ - invalid: accountForm.get('password').value.length < 8, - valid: accountForm.get('password').value.length >= 8 - }" - > - <app-svg-icon - *ngIf="accountForm.get('password').value.length >= 8" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="accountForm.get('password').value.length < 8" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'notValidate'" - /> - <p>8 caractères</p> - </li> - <li - [ngClass]="{ - invalid: !checkIfPasswordHasSpecialChar(accountForm.get('password').value), - valid: checkIfPasswordHasSpecialChar(accountForm.get('password').value) - }" - > - <app-svg-icon - *ngIf="checkIfPasswordHasSpecialChar(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="!checkIfPasswordHasSpecialChar(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'notValidate'" - /> - <p>un caractère spécial</p> - </li> - <li - [ngClass]="{ - invalid: !checkIfPasswordHasLowerCase(accountForm.get('password').value), - valid: checkIfPasswordHasLowerCase(accountForm.get('password').value) - }" - > - <app-svg-icon - *ngIf="checkIfPasswordHasLowerCase(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="!checkIfPasswordHasLowerCase(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'notValidate'" - /> - <p>un caractère en minuscule</p> - </li> - <li - [ngClass]="{ - invalid: !checkIfPasswordHasUpperCase(accountForm.get('password').value), - valid: checkIfPasswordHasUpperCase(accountForm.get('password').value) - }" - > - <app-svg-icon - *ngIf="checkIfPasswordHasUpperCase(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="!checkIfPasswordHasUpperCase(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'notValidate'" - /> - <p>un caractère en majuscule</p> - </li> - <li - [ngClass]="{ - invalid: !checkIfPasswordHasDigit(accountForm.get('password').value), - valid: checkIfPasswordHasDigit(accountForm.get('password').value) - }" - > - <app-svg-icon - *ngIf="checkIfPasswordHasDigit(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="!checkIfPasswordHasDigit(accountForm.get('password').value)" - [iconClass]="'validation-small'" - [folder]="'form'" - [icon]="'notValidate'" - /> - <p>un chiffre</p> - </li> - </ul> - <div fxLayout="row" fxLayoutAlign="none center" fxLayoutGap="13px"> - <input - formControlName="password" - class="form-input password" - autocomplete="on" - [type]="isShowPassword ? 'text' : 'password'" - /> - <app-svg-icon - tabindex="0" - [iconClass]="'validation grey hover'" - [folder]="'form'" - [icon]="'visibility'" - (click)="showPassword()" - (keyup.enter)="showPassword()" - /> - - <app-svg-icon - *ngIf="accountForm.get('password').valid" - [iconClass]="'validation'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="accountForm.get('password').invalid && accountForm.get('password').value" - [iconClass]="'validation'" - [folder]="'form'" - [icon]="'notValidate'" - /> - </div> - </div> - <div class="form-group" fxLayout="column"> - <label for="confirmPassword">Vérification du mot de passe</label> - <div fxLayout="row" fxLayoutAlign="none center" fxLayoutGap="13px"> - <input - formControlName="confirmPassword" - class="form-input password" - autocomplete="on" - [type]="isShowConfirmPassword ? 'text' : 'password'" - /> - <app-svg-icon - tabindex="0" - [iconClass]="'validation grey hover'" - [folder]="'form'" - [icon]="'visibility'" - (click)="showConfirmPassword()" - (keyup.enter)="showConfirmPassword()" - /> - <app-svg-icon - *ngIf="accountForm.get('confirmPassword').valid && accountForm.get('confirmPassword').value" - [iconClass]="'validation'" - [folder]="'form'" - [icon]="'validate'" - /> - <app-svg-icon - *ngIf="accountForm.get('confirmPassword').invalid && accountForm.get('confirmPassword').value" - [iconClass]="'validation'" - [folder]="'form'" - [icon]="'notValidate'" - /> - </div> - </div> - <div class="form-group" fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="20px"> - <app-button [variant]="'secondary'" [label]="'Annuler'" (action)="goHome()" /> - <app-button - [type]="'submit'" - [disabled]=" - accountForm.get('confirmPassword').invalid || - accountForm.get('password').invalid || - (oldPasswordNeeded && passwordError) - " - [variant]="'primary'" - [label]="'Envoyer'" - /> - </div> - </form> - </div> -</div> diff --git a/src/app/shared/components/password-form/password-form.component.scss b/src/app/shared/components/password-form/password-form.component.scss deleted file mode 100644 index 87b140313f0edaf319b0f47df0d9d5a7f25b1783..0000000000000000000000000000000000000000 --- a/src/app/shared/components/password-form/password-form.component.scss +++ /dev/null @@ -1,68 +0,0 @@ -@import 'color'; -@import 'layout'; -@import 'breakpoint'; -@import 'typography'; -.content { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; -} -.resetPage { - width: 100%; - max-width: 1000px; - box-sizing: border-box; - margin: auto; - min-height: 450px; - max-height: 75vh; - overflow-y: auto; - color: $grey-1; - background: $white; - border-radius: 8px; - border: 1px solid $grey-6; - padding: 1.5rem 2.5rem; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -h1 { - @include font-bold-24; -} -.form-group { - margin-bottom: 20px; - label { - color: $grey-2; - } - .resetPasswordForm { - max-width: 500px; - } - - .button { - margin-top: 20px; - } - - ul { - padding-left: 0; - margin: 0.5rem 0; - } - - li { - display: flex; - margin-left: 1%; - align-items: center; - p { - margin: 0 8px; - } - &.valid { - color: $green; - } - } - .special { - margin: 0; - } - .invalid { - color: $orange-warning; - } -} diff --git a/src/app/shared/components/password-form/password-form.component.ts b/src/app/shared/components/password-form/password-form.component.ts deleted file mode 100644 index d919204dd6b309b609e08cf6ad133937eee7a87d..0000000000000000000000000000000000000000 --- a/src/app/shared/components/password-form/password-form.component.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; -import { ActivatedRoute, Router } from '@angular/router'; -import { ProfileService } from '../../../profile/services/profile.service'; -import { AuthService } from '../../../services/auth.service'; -import { NotificationService } from '../../../services/notification.service'; -import { CustomRegExp } from '../../../utils/CustomRegExp'; -import { MustMatch } from '../../validator/form'; - -@Component({ - selector: 'app-password-form', - templateUrl: './password-form.component.html', - styleUrls: ['./password-form.component.scss'], -}) -export class PasswordFormComponent implements OnInit { - public accountForm: UntypedFormGroup; - public token: string; - public passwordError = false; - // Condition form - public isShowOldPassword = false; - public isShowConfirmPassword = false; - public isShowPassword = false; - // Form output - public oldPasswordNeeded = false; - - constructor( - private formBuilder: UntypedFormBuilder, - private router: Router, - private auth: AuthService, - private activatedRoute: ActivatedRoute, - private authService: AuthService, - private profileService: ProfileService, - private notificationService: NotificationService, - ) {} - - ngOnInit(): void { - this.activatedRoute.queryParams.subscribe((params) => { - this.token = params.token; - }); - if (this.auth.isLoggedIn()) { - this.oldPasswordNeeded = true; - } - this.initPasswordForm(); - } - - private initPasswordForm(): void { - if (!this.oldPasswordNeeded) { - this.accountForm = this.formBuilder.group( - { - password: ['', [Validators.required, Validators.pattern(CustomRegExp.PASSWORD)]], - confirmPassword: [''], - }, - { validator: MustMatch('password', 'confirmPassword') }, - ); - } else { - this.accountForm = this.formBuilder.group( - { - oldPassword: ['', [Validators.required, Validators.pattern(CustomRegExp.PASSWORD)]], - password: ['', [Validators.required, Validators.pattern(CustomRegExp.PASSWORD)]], - confirmPassword: [''], - }, - { validator: MustMatch('password', 'confirmPassword') }, - ); - } - } - - get fPassword(): Record<string, AbstractControl> { - return this.accountForm.controls; - } - - public showPassword(): void { - this.isShowPassword = !this.isShowPassword; - } - - public showConfirmPassword(): void { - this.isShowConfirmPassword = !this.isShowConfirmPassword; - } - - public showOldPassword(): void { - this.isShowOldPassword = !this.isShowOldPassword; - } - - public checkIfPasswordHasSpecialChar(password: string): boolean { - return Boolean(password.match(CustomRegExp.SPECHAR)); - } - - public checkIfPasswordHasDigit(password: string): boolean { - return Boolean(password.match(CustomRegExp.DIGIT)); - } - - public checkIfPasswordHasUpperCase(password: string): boolean { - return Boolean(password.match(CustomRegExp.UPPERCASE)); - } - - public checkIfPasswordHasLowerCase(password: string): boolean { - return Boolean(password.match(CustomRegExp.LOWERCASE)); - } - - public checkOldPassword(password: string): boolean { - if ( - password !== '' && - (!this.checkIfPasswordHasSpecialChar(password) || - !this.checkIfPasswordHasDigit(password) || - !this.checkIfPasswordHasUpperCase(password) || - !this.checkIfPasswordHasLowerCase(password)) - ) { - return false; - } else return true; - } - - public onSubmitPassword(): void { - // stop here if form is invalid - if (this.oldPasswordNeeded && !this.checkOldPassword(this.accountForm.value.oldPassword)) { - this.passwordError = true; - } else if (this.oldPasswordNeeded) { - // stop here if form is invalid - this.passwordError = false; - this.profileService - .changePassword(this.accountForm.value.password, this.accountForm.value.oldPassword) - .subscribe({ - next: () => { - this.notificationService.showSuccess( - 'Votre mot de passe a été réinitialisé avec succès.', - 'Veuillez vous connecter', - ); - this.passwordError = false; - }, - error: () => { - this.notificationService.showError('Échec de la réinitialisation de votre mot de passe'); - this.passwordError = true; - }, - complete: () => { - this.router.navigate(['/login']); - }, - }); - } else { - this.authService.resetPasswordApply(this.token, this.accountForm.value.password).subscribe({ - next: () => { - this.notificationService.showSuccess('Votre mot de passe a été réinitialisé avec succès.'); - }, - error: () => { - this.notificationService.showError('Échec de la réinitialisation de votre mot de passe'); - }, - complete: () => { - this.router.navigate(['']); - }, - }); - } - } - public goHome(): void { - this.router.navigateByUrl('news'); - } -}