Import des sources angular à partir de 'headup_app'

This commit is contained in:
Rampeur
2025-08-11 23:26:29 +02:00
parent 7dcb426ef5
commit 0a6cbc0c00
335 changed files with 64362 additions and 0 deletions
@@ -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 }
}
}