Import des sources angular à partir de 'headup_app'
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<div class="banner bg-navy light text-center mat-elevation-z2">
|
||||
<div class="d-flex justify-content-center text-start">
|
||||
<img [src]="user.image" class="user-img" [alt]="user.username" />
|
||||
<div class="ms-3">
|
||||
<h4>{{ bannerTitle }}</h4>
|
||||
<button mat-raised-button color="cyan" [routerLink]="['/profile', user.username]">
|
||||
<mat-icon aria-label="Voir le compte" fontIcon="person"></mat-icon> Mon compte
|
||||
</button>
|
||||
<button mat-raised-button color="warn" routerLink="/settings" class="ms-2">
|
||||
<mat-icon aria-label="Modifier le compte" fontIcon="settings"></mat-icon> Paramètres
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="credentials-page">
|
||||
<h1>{{title}}</h1>
|
||||
<mat-divider></mat-divider>
|
||||
<app-list-errors [errors]="errors"></app-list-errors>
|
||||
<div class="container page mt-4">
|
||||
<div class="row">
|
||||
<div class="col-md-6 offset-md-3 col-xs-12">
|
||||
<form class="row row-cols-lg-auto" [formGroup]="credentialsForm" (ngSubmit)="submitForm()">
|
||||
<fieldset [disabled]="isSubmitting" class="w-100">
|
||||
<legend [hidden]="true">Mise à jour du mot de passe</legend>
|
||||
<div class="col-12">
|
||||
<mat-form-field appearance="fill" class="w-100">
|
||||
<mat-label>Mot de passe</mat-label>
|
||||
<input matInput type="password" placeholder="Nouveau mot de passe" formControlName="password">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<mat-form-field appearance="fill" class="w-100">
|
||||
<mat-label>Confirmation du mot de passe</mat-label>
|
||||
<input matInput type="password" placeholder="Confirmez votre nouveau mot de passe" formControlName="confirmPassword">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button mat-raised-button color="primary" [disabled]="!credentialsForm.valid" type="submit" class="float-sm-end">{{ btnUpdateTitle }}</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Credentials */
|
||||
@use 'variable' as var;
|
||||
|
||||
.banner {
|
||||
background-color: var.$sidebar-footer;
|
||||
padding: 1.6rem 0 1.3rem 0;
|
||||
margin: -1.5rem -1.5rem 1.5rem -1.5rem;
|
||||
.user-img {
|
||||
width: var.$user-img-size;
|
||||
height: var.$user-img-size;
|
||||
border-radius: var.$user-img-size;
|
||||
}
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
p {
|
||||
margin: 0 auto .5rem;
|
||||
color: var.$muted;
|
||||
max-width: 450px;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CredentialsComponent } from './credentials.component';
|
||||
|
||||
describe('CredentialsComponent', () => {
|
||||
let component: CredentialsComponent;
|
||||
let fixture: ComponentFixture<CredentialsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [CredentialsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CredentialsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { AbstractControl, FormsModule, ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators, ValidatorFn, ValidationErrors } from '@angular/forms';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { Errors, User } from 'src/app/core/models';
|
||||
import { UserService } from 'src/app/core/services';
|
||||
import { ListErrorsComponent } from 'src/app/components/shared';
|
||||
|
||||
@Component({
|
||||
selector: 'app-credentials',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterLink, FormsModule, ReactiveFormsModule,
|
||||
MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, MatDividerModule,
|
||||
ListErrorsComponent
|
||||
],
|
||||
templateUrl: './credentials.component.html',
|
||||
styleUrl: './credentials.component.scss'
|
||||
})
|
||||
export class CredentialsComponent implements OnInit, OnDestroy {
|
||||
private _user: Subscription = new Subscription();
|
||||
title = 'Modifier le mot de passe';
|
||||
bannerTitle = '';
|
||||
btnUpdateTitle = 'Mettre à jour';
|
||||
btnLogoutTitle = 'Se déconnecter';
|
||||
user: Partial<User> = {} as Partial<User>;
|
||||
credentialsForm: UntypedFormGroup;
|
||||
errors: Errors = { errors: {} };
|
||||
isSubmitting = false;
|
||||
destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private titleService: Title,
|
||||
private userService: UserService,
|
||||
private fb: UntypedFormBuilder
|
||||
) {
|
||||
this.credentialsForm = this.fb.group({
|
||||
password: ['', Validators.required],
|
||||
confirmPassword: ['', Validators.required]
|
||||
}, { validators: this.checkPasswords });
|
||||
}
|
||||
|
||||
get f() {
|
||||
return this.credentialsForm.controls;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.titleService.setTitle(`Head Up - ${this.title}`);
|
||||
Object.assign(this.user, this.userService.getCurrentUser());
|
||||
this.credentialsForm.patchValue(this.user);
|
||||
if (this.user.username) {
|
||||
this.bannerTitle = `@${this.user.username}`;
|
||||
} else {
|
||||
this.bannerTitle = `${this.user.firstname} ${this.user.lastname}`;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._user.unsubscribe();
|
||||
}
|
||||
|
||||
submitForm() {
|
||||
this.isSubmitting = true;
|
||||
this.updateUser(this.credentialsForm.value);
|
||||
const user$: Observable<{ user: User }> = this.userService.update(this.user).pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._user = user$.subscribe({
|
||||
next: ({ user }) => void this.router.navigateByUrl('/profile/' + user.username),
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateUser(values: NonNullable<unknown>) {
|
||||
Object.assign(this.user, values);
|
||||
}
|
||||
|
||||
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
|
||||
const pass = group.get('password')!.value;
|
||||
const confirmPass = group.get('confirmPassword')!.value
|
||||
return pass === confirmPass ? null : { notSame: true }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user