Skip to content
This repository was archived by the owner on Nov 28, 2025. It is now read-only.

Commit a1aab6f

Browse files
committed
✨ mis en place de la feature pour la reinitialisation du mot de passe
1 parent 6a417f8 commit a1aab6f

File tree

11 files changed

+103
-28
lines changed

11 files changed

+103
-28
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import { getSelectors } from '@ngrx/router-store';
22

3-
export const { selectRouteParams } = getSelectors();
3+
export const { selectRouteParams, selectQueryParams } = getSelectors();
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
export interface Credentials {
22
email: string;
33
password: string;
4+
}
5+
6+
export interface ResetPasswordCredentials {
7+
email: string;
8+
password: string;
9+
password_confirmation: string;
10+
token: string;
411
}

src/app/modules/authentication/pages/reset-password/reset-password.component.html

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ <h2 class="mt-6 text-3xl font-semibold text-slate-900">Réinitialisation Mot de
66
</p>
77
</div>
88

9-
<form action="#" method="POST" class="mt-8 space-y-6">
10-
<!-- Password Reset Token -->
11-
<input type="hidden" name="token" value="token-url" />
9+
<!-- Session Status -->
10+
<cosna-success *ngIf="message$ | async; let message" [message]="message" class="mt-4"></cosna-success>
1211

12+
<!-- Validation Errors -->
13+
<cosna-errors *ngIf="error$ | async; let error" [message]="error" class="mt-4"></cosna-errors>
14+
15+
<form [formGroup]="form" (submit)="submit()" class="mt-8 space-y-6">
1316
<!-- Email Address -->
1417
<div>
1518
<cosna-input-overlaping-label
1619
label="Adresse E-mail"
1720
name="email"
18-
value=""
21+
formControlName="email"
1922
></cosna-input-overlaping-label>
2023
</div>
2124

@@ -24,7 +27,7 @@ <h2 class="mt-6 text-3xl font-semibold text-slate-900">Réinitialisation Mot de
2427
<cosna-input-overlaping-label
2528
label="Nouveau Mot de passe"
2629
name="password"
27-
value=""
30+
formControlName="password"
2831
[type]="'password'"
2932
></cosna-input-overlaping-label>
3033
</div>
@@ -34,15 +37,15 @@ <h2 class="mt-6 text-3xl font-semibold text-slate-900">Réinitialisation Mot de
3437
<cosna-input-overlaping-label
3538
label="Confirmer Mot de passe"
3639
name="password_confirmation"
37-
value=""
40+
formControlName="password_confirmation"
3841
[type]="'password'"
3942
></cosna-input-overlaping-label>
4043
</div>
4144

4245
<div class="flex items-center justify-end">
43-
<cosna-button-primary type="submit">
46+
<cosna-button-primary type="submit" class="space-x-3" [loading$]="(loading$)">
4447
Réinitialiser Mot de passe
4548
</cosna-button-primary>
46-
</div>
49+
</div>
4750

4851
</form>
Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
11
import { Component, OnInit } from '@angular/core';
2+
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
3+
import { Store } from '@ngrx/store';
4+
import { map, Observable } from 'rxjs';
5+
6+
import {
7+
selectError,
8+
selectLoading,
9+
selectMessage,
10+
selectResetPasswordToken
11+
} from '../../store/auth.selectors';
12+
import { resetPasswordAction } from '../../store/auth.actions';
13+
import { PasswordRules } from '../../rules/password.rules';
214

315
@Component({
416
templateUrl: './reset-password.component.html',
517
})
618
export class ResetPasswordComponent implements OnInit {
19+
public form: FormGroup = this.formBuilder.group({
20+
email: ['', [Validators.required, Validators.email]],
21+
password: ['', [Validators.required, Validators.minLength(2)]],
22+
password_confirmation: ['', [Validators.required, Validators.minLength(2)]],
23+
}, { validators: [PasswordRules.match('password', 'password_confirmation')] });
724

8-
constructor() { }
25+
public error$: Observable<string | null> = this.store.select(selectError);
926

10-
ngOnInit(): void {
11-
}
27+
public message$: Observable<string | null> = this.store.select(selectMessage);
28+
29+
public loading$: Observable<boolean> = this.store.select(selectLoading);
30+
31+
public token$: Observable<string | null> = this.store.select(selectResetPasswordToken);
1232

33+
constructor(private formBuilder: FormBuilder, private store: Store) { }
34+
35+
ngOnInit(): void {}
36+
37+
public submit() {
38+
if (this.form.valid) {
39+
this.token$.pipe(map((token) => token)).subscribe((value) => {
40+
let credentials = { ...this.form.getRawValue(), token: value };
41+
this.store.dispatch(resetPasswordAction({ credentials }));
42+
});
43+
}
44+
}
1345
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { AbstractControl, ValidatorFn } from '@angular/forms';
2+
3+
export class PasswordRules {
4+
static match(controlName: string, checkControlName: string): ValidatorFn {
5+
return (controls: AbstractControl) => {
6+
const control = controls.get(controlName);
7+
const checkControl = controls.get(checkControlName);
8+
if (checkControl?.errors && !checkControl.errors['matching']) {
9+
return null;
10+
}
11+
if (control?.value !== checkControl?.value) {
12+
controls.get(checkControlName)?.setErrors({ matching: true });
13+
return { matching: true };
14+
} else {
15+
return null;
16+
}
17+
};
18+
}
19+
}

src/app/modules/authentication/services/auth.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { Injectable } from '@angular/core';
22
import { HttpClient } from '@angular/common/http';
33
import { Observable } from 'rxjs';
44

5-
import { AuthResponse, User } from '@app/modules/user/interfaces/user.interface';
6-
import { Credentials } from '../interfaces/credentials.interface';
75
import { environment } from 'environments/environment';
6+
import { AuthResponse, User } from '@app/modules/user/interfaces/user.interface';
7+
import { Credentials, ResetPasswordCredentials } from '../interfaces/credentials.interface';
88

99
@Injectable({
1010
providedIn: 'root'
@@ -26,10 +26,10 @@ export class AuthService {
2626
);
2727
}
2828

29-
public resetPassword(email: string, password: string, confirmPassword: string): Observable<any> {
29+
public resetPassword(credentials: ResetPasswordCredentials): Observable<any> {
3030
return this.http.post(
3131
`${environment.apiUrl}/reset-password`,
32-
{ email, password, confirmPassword }
32+
credentials
3333
);
3434
}
3535

src/app/modules/authentication/store/auth.actions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createAction, props } from '@ngrx/store';
2-
import { Credentials } from '../interfaces/credentials.interface';
2+
import { Credentials, ResetPasswordCredentials } from '../interfaces/credentials.interface';
33

44
import { User } from '@app/modules/user/interfaces/user.interface';
55

@@ -35,12 +35,12 @@ export const forgotPasswordFailureAction = createAction(
3535

3636
export const resetPasswordAction = createAction(
3737
'[Auth] Reset Password',
38-
props<{ email: string, password: string, confirmPassword: string }>()
38+
props<{ credentials: ResetPasswordCredentials }>()
3939
);
4040

4141
export const resetPasswordSuccessAction = createAction(
4242
'[Auth] Reset Password Success',
43-
props<{ message: string, user: User }>()
43+
props<{ message: string }>()
4444
);
4545

4646
export const resetPasswordFailureAction = createAction(

src/app/modules/authentication/store/auth.effects.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { catchError, map, switchMap } from 'rxjs/operators';
66

77
import * as AuthActions from './auth.actions';
88
import { AuthService } from '../services/auth.service';
9-
import { Credentials } from '../interfaces/credentials.interface';
9+
import { Credentials, ResetPasswordCredentials } from '../interfaces/credentials.interface';
1010
import { AuthResponse, User } from '@app/modules/user/interfaces/user.interface';
1111
import { AccessTokenService } from '../services/access-token.service';
1212

@@ -38,12 +38,8 @@ export class AuthEffects {
3838
ofType(AuthActions.forgotPasswordAction),
3939
switchMap(({ email }: { email: string }) =>
4040
this.authService.forgotPassword(email).pipe(
41-
map(({ message }: { message: string }) => {
42-
console.log(message);
43-
return AuthActions.forgotPasswordSuccessAction({ message })
44-
}),
41+
map(({ message }: { message: string }) => AuthActions.forgotPasswordSuccessAction({ message })),
4542
catchError((error) => {
46-
console.log(error);
4743
return of(
4844
AuthActions.forgotPasswordFailureAction({
4945
error: error.error?.message ?? 'Unknown error occurred',
@@ -56,6 +52,18 @@ export class AuthEffects {
5652

5753
resetPasswordEffect = createEffect(() => this.actions$.pipe(
5854
ofType(AuthActions.resetPasswordAction),
55+
switchMap(({ credentials }: { credentials: ResetPasswordCredentials }) =>
56+
this.authService.resetPassword(credentials).pipe(
57+
map(({ message }: { message: string }) => AuthActions.resetPasswordSuccessAction({ message })),
58+
catchError((error) => {
59+
return of(
60+
AuthActions.resetPasswordFailureAction({
61+
error: error.error?.message ?? 'Unknown error occurred',
62+
})
63+
)
64+
}
65+
))
66+
)
5967
));
6068

6169
getCurrentUserEffect = createEffect(() =>

src/app/modules/authentication/store/auth.reducer.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,12 @@ export const authReducer = createReducer(
6565
),
6666
on(
6767
AuthActions.resetPasswordSuccessAction,
68-
(state: AuthState, { message, user }: { message: string, user: User }): AuthState => {
68+
(state: AuthState, { message }: { message: string }): AuthState => {
6969
return {
7070
...state,
7171
isLoading: false,
7272
error: null,
7373
message,
74-
user,
7574
}
7675
}
7776
),

src/app/modules/authentication/store/auth.selectors.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { createFeatureSelector, createSelector } from '@ngrx/store';
22

3+
import { selectQueryParams } from '@app/core/store/router.selectors';
34
import { AuthState } from '../interfaces/state.interface';
45
import { authFeatureKey } from './auth.reducer';
6+
import { Params } from '@angular/router';
57

68
const authSelectorFeature = createFeatureSelector<AuthState>(authFeatureKey);
79

@@ -28,4 +30,9 @@ export const selectMessage = createSelector(
2830
export const selectLoading = createSelector(
2931
authSelectorFeature,
3032
(state: AuthState) => state.isLoading
33+
);
34+
35+
export const selectResetPasswordToken = createSelector(
36+
selectQueryParams,
37+
(params: Params) => params['token']
3138
);

0 commit comments

Comments
 (0)