diff --git a/src/app/annuaire/annuaire.component.ts b/src/app/annuaire/annuaire.component.ts index c8c1a50713d28d44506d036082dcff79f9a820b0..69872baf58d23d374ee3ef1c7385e2caaa195574 100644 --- a/src/app/annuaire/annuaire.component.ts +++ b/src/app/annuaire/annuaire.component.ts @@ -9,7 +9,7 @@ import { SearchQuery, SearchResults } from './models/searchQuery.model'; templateUrl: './annuaire.component.html', styleUrls: ['./annuaire.component.scss'], }) -export class AnnuaireComponent implements OnInit { +export class AnnuaireComponent { constructor(private searchService: SearchService, private authService: AuthService) {} public userList: UserAnnuary[] = []; public searchedValue: string; @@ -18,18 +18,16 @@ export class AnnuaireComponent implements OnInit { public nextPage: number = 1; public filterActive: boolean = false; - ngOnInit(): void { - this.getUsers({ queryParam: '', page: 1, jobFilters: [], employerFilter: [] }); - } public getUsers(params: SearchQuery): void { if (this.userIsLoggedIn()) { - if (params.employerFilter?.length || params.jobFilters.length) { + this.searchService.annuaireSearchQuery = params; + if (params.employerFilters?.length || params.jobFilters?.length) { this.filterActive = true; } else { this.filterActive = false; } this.searchService - .searchUserRegistry(params.queryParam, params.page, params.jobFilters, params.employerFilter) + .searchUserRegistry(params.queryParam, params.page, params.jobFilters, params.employerFilters) .subscribe((res: SearchResults) => { this.userList = res.docs; this.totalUserResult = res.count; diff --git a/src/app/annuaire/filter-modal/filter-modal.component.scss b/src/app/annuaire/filter-modal/filter-modal.component.scss index 2f81cc71212d80c7552ef50e0ea437a5c355ad1f..95c6f221291e4c3dd645325a15a12192b3e70f74 100644 --- a/src/app/annuaire/filter-modal/filter-modal.component.scss +++ b/src/app/annuaire/filter-modal/filter-modal.component.scss @@ -7,17 +7,10 @@ @import '../../../assets/scss/z-index'; .modalemployers { - left: 212px; - - @media #{$large-desktop} { - left: 273px; - } + left: 515px; } .modaljobs { - left: 331px; - @media #{$large-desktop} { - left: 417px; - } + left: 412px; } .maxModal .blockLigne { diff --git a/src/app/annuaire/models/searchQuery.model.ts b/src/app/annuaire/models/searchQuery.model.ts index a81c86e731b5c551894f1569cb793e4c0ae033a1..c9c3cd9698216c3da26ea2125f8c3e6b0a6336ea 100644 --- a/src/app/annuaire/models/searchQuery.model.ts +++ b/src/app/annuaire/models/searchQuery.model.ts @@ -4,7 +4,7 @@ export interface SearchQuery { queryParam: string; page: number; jobFilters?: string[]; - employerFilter?: string[]; + employerFilters?: string[]; } export interface SearchResults { count: number; diff --git a/src/app/annuaire/result-list/result-list.component.html b/src/app/annuaire/result-list/result-list.component.html index 434d97ac2fcca074b3202395ea36a958dd345640..1582d326c3b31723a0619ef1cdcd6bca9ec5ddb8 100644 --- a/src/app/annuaire/result-list/result-list.component.html +++ b/src/app/annuaire/result-list/result-list.component.html @@ -1,8 +1,13 @@ <div class="results notEmpty" *ngIf="isLogged && userList.length" [ngClass]="{ filterActive: filterActive }"> <div class="userNumber"> - {{ userList.length }} <span *ngIf="showPagination"> sur {{ totalUserResult }} </span> utilisateurs trouvés + {{ userList.length }} utilisateur(s)<span *ngIf="showPagination"> sur {{ totalUserResult }} </span> </div> - <div class="singleUser" *ngFor="let user of userList; let index = index" (click)="goToUser(user._id)"> + <div + class="singleUser" + [ngClass]="{ singleResult: userList.length == 1 }" + *ngFor="let user of userList; let index = index" + (click)="goToUser(user._id)" + > <div class="avatar-container"> <app-svg-icon class="avatar" [type]="'avatar'" [icon]="'defaultAvatar'" [iconClass]="'icon-40'"></app-svg-icon> </div> @@ -13,7 +18,9 @@ <div class="employer" *ngIf="user.employer">{{ user.employer.name }}</div> </div> <div class="pagination" *ngIf="showPagination"> - <div class="text">{{ userList.length }} utilisateurs affichés sur {{ totalUserResult }} utilisateurs trouvés.</div> + <div class="text"> + {{ userList.length }} utilisateur(s) affiché(s) sur {{ totalUserResult }} utilisateur(s) trouvé(s). + </div> <app-button [style]="buttonTypeEnum.modalSecondary" [type]="'form'" diff --git a/src/app/annuaire/result-list/result-list.component.scss b/src/app/annuaire/result-list/result-list.component.scss index 63d3022b6b865fe0fb5c5148cae76dfd0d1c2492..6558b66bf6c6f3bb5e33b29d0b99f7fec9e3f342 100644 --- a/src/app/annuaire/result-list/result-list.component.scss +++ b/src/app/annuaire/result-list/result-list.component.scss @@ -128,4 +128,7 @@ color: $grey-3; } } + .singleResult { + border-bottom: none; + } } diff --git a/src/app/annuaire/search-bar/search-bar.component.html b/src/app/annuaire/search-bar/search-bar.component.html index 8012b13d9e4ae05f85e45189a7d45d3b382fc08b..5eb03a96ce0b06ca424162297054cd56afc92a8e 100644 --- a/src/app/annuaire/search-bar/search-bar.component.html +++ b/src/app/annuaire/search-bar/search-bar.component.html @@ -29,13 +29,13 @@ type="button" fxLayout="row" [ngClass]="{ - selected: modalTypeOpened === TypeModal.employers, - containCheckedFilters: numberEmployersChecked + selected: modalTypeOpened === TypeModal.jobs, + containCheckedFilters: numberJobChecked }" fxLayoutAlign="space-between center" - (click)="openModal(TypeModal.employers)" + (click)="openModal(TypeModal.jobs)" > - <span>Employeur</span> + <span>Fonction</span> <div class="arrow"></div> </button> <button @@ -43,20 +43,20 @@ type="button" fxLayout="row" [ngClass]="{ - selected: modalTypeOpened === TypeModal.jobs, - containCheckedFilters: numberJobChecked + selected: modalTypeOpened === TypeModal.employers, + containCheckedFilters: numberEmployersChecked }" fxLayoutAlign="space-between center" - (click)="openModal(TypeModal.jobs)" + (click)="openModal(TypeModal.employers)" > - <span>Fonction</span> + <span>Employeur</span> <div class="arrow"></div> </button> <div *ngIf="modalTypeOpened"> <app-filter-modal [modalType]="modalTypeOpened" - [checkedFilters]="checkedFilterList" + [checkedFilters]="searchService.checkedFilterList" [filtersTypes]="getModalCategory()" (searchEvent)="fetchResults($event)" (closeEvent)="closeModal()" @@ -66,10 +66,15 @@ </div> </div> - <div *ngIf="checkedFilterList.length" fxLayout="row wrap" fxLayoutGap="4px" class="filterTags isntPhoneContent"> + <div + *ngIf="searchService.checkedFilterList.length" + fxLayout="row wrap" + fxLayoutGap="4px" + class="filterTags isntPhoneContent" + > <div class="title">Filtres :</div> <app-button - *ngFor="let filter of checkedFilterList" + *ngFor="let filter of searchService.checkedFilterList" [style]="buttonTypeEnum.TagCloudButton" [text]="filter" (action)="removeFilter(filter)" diff --git a/src/app/annuaire/search-bar/search-bar.component.ts b/src/app/annuaire/search-bar/search-bar.component.ts index 57607b60231c73f7ef3b628c98411118b88ebb2c..7debfcd74b042242b5caa6ce2a3017b03da25282 100644 --- a/src/app/annuaire/search-bar/search-bar.component.ts +++ b/src/app/annuaire/search-bar/search-bar.component.ts @@ -1,8 +1,8 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; +import { forkJoin } from 'rxjs'; import { ButtonType } from '../../shared/components/button/buttonType.enum'; -import { Filter } from '../../structure-list/models/filter.model'; import { SearchService } from '../../structure-list/services/search.service'; import { TypeModal } from '../enums/TypeModal.enum'; @@ -21,12 +21,10 @@ export class SearchBarComponent implements OnInit, OnChanges { public buttonTypeEnum = ButtonType; public searchForm: FormGroup; public modalTypeOpened: TypeModal; - public checkedFilterList: string[] = []; public numberEmployersChecked = 0; public numberJobChecked = 0; public jobTypes: string[] = []; public employerTypes: string[] = []; - public queryString: string; public jobFilterChecked: string[] = []; public employerFilterChecked: string[] = []; @@ -36,42 +34,45 @@ export class SearchBarComponent implements OnInit, OnChanges { private activatedRoute: ActivatedRoute, private route: ActivatedRoute, private router: Router, - private searchService: SearchService - ) { - this.searchForm = this.fb.group({ - searchTerm: this.activatedRoute.snapshot.queryParamMap.get('search') - ? this.activatedRoute.snapshot.queryParamMap.get('search') - : '', - }); - } + public searchService: SearchService + ) {} ngOnInit(): void { // Will store the different categories this.getData(); - this.queryString = this.activatedRoute.snapshot.queryParamMap.get('search'); - if (this.queryString) { - const filters: Filter[] = []; - filters.push(new Filter('query', this.queryString)); - this.searchEvent.emit(filters); + let queryString = this.activatedRoute.snapshot.queryParamMap.get('search'); + // Use existing query if back to the page or init the query + if (!this.searchService.annuaireSearchQuery) { + this.searchService.annuaireSearchQuery = { queryParam: '', page: 1, jobFilters: [], employerFilters: [] }; + } + if (queryString) { + this.searchService.annuaireSearchQuery.queryParam = queryString; } + this.searchForm = this.fb.group({ + searchTerm: this.searchService.annuaireSearchQuery.queryParam, + }); + this.searchEvent.emit(this.searchService.annuaireSearchQuery); } ngOnChanges(changes: SimpleChanges): void { if (changes.shouldResetFilters && changes.shouldResetFilters.currentValue !== 0) this.resetFilters(); if (changes.shouldShowMore && !changes.shouldShowMore.firstChange) { + const term = this.searchForm.get('searchTerm').value || ''; this.searchEvent.emit({ - queryParam: this.searchForm.get('searchTerm').value, + queryParam: term, page: changes.shouldShowMore.currentValue, jobFilters: this.jobFilterChecked, - employerFilter: this.employerFilterChecked, + employerFilters: this.employerFilterChecked, }); } } // Get the categories for each modal type private getData(): void { - this.searchService.getJobs().subscribe((res) => { - this.jobTypes = res; - }); - this.searchService.getEmployers().subscribe((res) => { - this.employerTypes = res; + forkJoin({ + job: this.searchService.getJobs(), + employer: this.searchService.getEmployers(), + }).subscribe((data) => { + this.jobTypes = data.job; + this.employerTypes = data.employer; + this.countCheckedFilters(); }); } @@ -107,16 +108,16 @@ export class SearchBarComponent implements OnInit, OnChanges { relativeTo: this.route, }); } - this.splitFilters(this.checkedFilterList); + this.splitFilters(this.searchService.checkedFilterList); this.searchEvent.emit({ queryParam: term || '', jobFilters: this.jobFilterChecked, - employerFilter: this.employerFilterChecked, + employerFilters: this.employerFilterChecked, }); } public fetchResults(checkedFilters: string[]): void { - this.checkedFilterList = checkedFilters; + this.searchService.checkedFilterList = checkedFilters; const inputTerm = this.searchForm.get('searchTerm').value; this.closeModal(); this.applyFilter(inputTerm); @@ -124,8 +125,12 @@ export class SearchBarComponent implements OnInit, OnChanges { // Check if some modules is checked on filter and store number of modules checked public countCheckedFilters(): void { - this.numberJobChecked = this.checkedFilterList.filter((filter) => this.jobTypes.includes(filter)).length; - this.numberEmployersChecked = this.checkedFilterList.filter((filter) => this.employerTypes.includes(filter)).length; + this.numberJobChecked = this.searchService.checkedFilterList.filter((filter) => + this.jobTypes.includes(filter) + ).length; + this.numberEmployersChecked = this.searchService.checkedFilterList.filter((filter) => + this.employerTypes.includes(filter) + ).length; } public getModalCategory(): string[] | Error { @@ -155,25 +160,25 @@ export class SearchBarComponent implements OnInit, OnChanges { } public resetFilters(): void { - this.checkedFilterList = []; + this.searchService.checkedFilterList = []; this.numberEmployersChecked = 0; this.numberJobChecked = 0; this.employerFilterChecked = []; this.jobFilterChecked = []; - this.searchEvent.emit({ queryParam: '', jobFilters: [], employerFilter: [] }); + this.searchEvent.emit({ queryParam: '', jobFilters: [], employerFilters: [] }); this.router.navigate(['/annuaire']); this.searchForm.reset(); } public removeFilter(filter: string): void { - const index = this.checkedFilterList.findIndex((checkedFilter: string) => checkedFilter === filter); - this.checkedFilterList.splice(index, 1); + const index = this.searchService.checkedFilterList.findIndex((checkedFilter: string) => checkedFilter === filter); + this.searchService.checkedFilterList.splice(index, 1); const inputTerm = this.searchForm.get('searchTerm').value; - this.splitFilters(this.checkedFilterList); + this.splitFilters(this.searchService.checkedFilterList); this.countCheckedFilters(); this.searchEvent.emit({ queryParam: inputTerm || '', - jobFilters: this.checkedFilterList.length ? this.jobFilterChecked : [], - employerFilter: this.checkedFilterList.length ? this.employerFilterChecked : [], + jobFilters: this.jobFilterChecked, + employerFilters: this.employerFilterChecked, }); } } diff --git a/src/app/profile/edit/edit.component.html b/src/app/profile/edit/edit.component.html index 38c78c377e48a75649b8abedb1e4b88a518ce46e..2c2d53817eab102c7876c8146655cdc1f29646d2 100644 --- a/src/app/profile/edit/edit.component.html +++ b/src/app/profile/edit/edit.component.html @@ -193,7 +193,7 @@ maxlength="500" [(ngModel)]="userProfile.description" ></textarea> - <p class="descriptionLength">{{ userProfile.description?.length }} / 500</p> + <p class="descriptionLength">{{ userProfile.description?.length || 0 }} / 500</p> </div> </div> diff --git a/src/app/profile/edit/edit.component.ts b/src/app/profile/edit/edit.component.ts index ca4a6e47513ef01f48846487875952a5697faf60..925001c88c0929b86b3b80d33801c1aa9df0bdc1 100644 --- a/src/app/profile/edit/edit.component.ts +++ b/src/app/profile/edit/edit.component.ts @@ -1,4 +1,5 @@ import { ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; +import { Router } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { forkJoin, of } from 'rxjs'; import { catchError, first, map } from 'rxjs/operators'; @@ -62,7 +63,8 @@ export class EditComponent implements OnInit { private profileService: ProfileService, private notificationService: NotificationService, private cdr: ChangeDetectorRef, - private authService: AuthService + private authService: AuthService, + private router: Router ) {} ngOnInit(): void { @@ -100,7 +102,7 @@ export class EditComponent implements OnInit { return this.userProfile.surname !== ''; } public descriptionValid(): boolean { - return this.userProfile.description.length <= 500; + return this.userProfile.description?.length <= 500; } public emailValid(email: string): boolean { return !!email.match(CustomRegExp.EMAIL); @@ -196,7 +198,7 @@ export class EditComponent implements OnInit { phone: this.userProfile.phone, }) .subscribe((user: User) => { - this.notificationService.showSuccess('Vos coordonnées ont bien été mises à jour'); + this.notificationService.showSuccess('Vos informations ont bien été enregistrées'); //Update localstorage const updatedUser = { ...this.authService.userSubject.value, @@ -207,6 +209,7 @@ export class EditComponent implements OnInit { localStorage.setItem('user', JSON.stringify(updatedUser)); this.authService.userSubject.next(updatedUser); this.updateInitialProfile(); + this.router.navigate(['/profile']); }); } @@ -221,19 +224,24 @@ export class EditComponent implements OnInit { map((res) => res), catchError(() => of(this.selectJob)) ), - profile: this.profileService.updateProfile(this.selectedEmployer.name, this.selectedJob.name).pipe( - map((res) => res), - catchError(() => of()) - ), }).subscribe(() => { - this.notificationService.showSuccess('Vos informations ont bien été enregistrées'); + this.profileService.updateProfile(this.selectedEmployer.name, this.selectedJob.name).subscribe( + () => { + this.router.navigate(['/profile']); + this.notificationService.showSuccess('Vos informations ont bien été enregistrées'); + }, + () => { + this.notificationService.showError("Vos informations n'ont pas été enregistrées", 'Une erreur est survenue'); + } + ); }); } public confirmDescription(): void { this.profileService.updateDescription(this.userProfile.description).subscribe(() => { - this.notificationService.showSuccess('Vos description a bien été enregistrée'); + this.notificationService.showSuccess('Vos informations ont bien été enregistrées'); this.updateInitialProfile(); + this.router.navigate(['/profile']); }); } diff --git a/src/app/profile/profile-structure/profile-structure.component.html b/src/app/profile/profile-structure/profile-structure.component.html index 5d6c08ddcb9acd126f5864e93cb248614c9cb7be..05ee4b9554bd2bbf0494c475c52a5ab297d0e364 100644 --- a/src/app/profile/profile-structure/profile-structure.component.html +++ b/src/app/profile/profile-structure/profile-structure.component.html @@ -33,7 +33,6 @@ <p class="section-title">informations</p> <div fxLayout="row" fxLayoutAlign="space-between center" fxLayoutGap="12px"> <app-button - *ngIf="!isPublic" class="hide-on-mobile" [type]="'button'" [iconBtn]="'eyePassword'" @@ -45,7 +44,6 @@ [routerLinkActive]="'active'" ></app-button> <app-button - *ngIf="!isPublic" class="hide-on-desktop" [type]="'button'" [iconBtn]="'eyePassword'" diff --git a/src/app/profile/structure-edition-summary/structure-edition-summary.component.html b/src/app/profile/structure-edition-summary/structure-edition-summary.component.html index b48893764b6646b453adb5102c2ea234832b3500..57445aa197ca3693327df377349ad9d082b93144 100644 --- a/src/app/profile/structure-edition-summary/structure-edition-summary.component.html +++ b/src/app/profile/structure-edition-summary/structure-edition-summary.component.html @@ -163,7 +163,7 @@ <app-no-information *ngIf="!hasWebsite() && !hasSocialNetworks()"></app-no-information> <ng-container *ngIf="hasWebsite() || hasSocialNetworks()"> <div *ngIf="structure.website"> - <a href="structure.website">{{ structure.website }}</a> + <a href="{{ structure.website }}">{{ structure.website }}</a> </div> <!-- Social networks--> diff --git a/src/app/profile/structure-members-management/structure-members-management.component.html b/src/app/profile/structure-members-management/structure-members-management.component.html index 903dffbfb5d206e6533879f89fb5f761c2698142..6d2f1c3da4c555c72cea800d2cf733e2494d2aaa 100644 --- a/src/app/profile/structure-members-management/structure-members-management.component.html +++ b/src/app/profile/structure-members-management/structure-members-management.component.html @@ -4,7 +4,9 @@ <div fxLayout="row" fxLayoutAlign="space-between center" fxFill> <div fxLayout="row" fxLayoutAlign="start center" class="headerBack"> <app-svg-icon [iconClass]="'backArrow'" [type]="'ico'" [icon]="'arrowBack'" (click)="goBack()"></app-svg-icon> - <h1>Gérer les membres<br />de {{ structure.structureName }}</h1> + <h1> + Gérer les membres de <span>{{ structure.structureName }}</span> + </h1> </div> <app-button [style]="buttonTypeEnum.Secondary" diff --git a/src/app/profile/structure-members-management/structure-members-management.component.scss b/src/app/profile/structure-members-management/structure-members-management.component.scss index 17db43964ca8645c694cb0e6761ffd130195e2ec..d0dbc5e75385ac44432e50ad0c3b9f63decfb8e1 100644 --- a/src/app/profile/structure-members-management/structure-members-management.component.scss +++ b/src/app/profile/structure-members-management/structure-members-management.component.scss @@ -14,6 +14,9 @@ } .headerBack { cursor: pointer; + span { + color: $red; + } } h1 { @include lato-regular-24; diff --git a/src/app/structure-list/components/structure-details/structure-details.component.ts b/src/app/structure-list/components/structure-details/structure-details.component.ts index 7fc9768db01d0e96a16ea666123bb449f9e39dfc..e7375bc58f2d9dceeaa45ac9004c4720c503cf42 100644 --- a/src/app/structure-list/components/structure-details/structure-details.component.ts +++ b/src/app/structure-list/components/structure-details/structure-details.component.ts @@ -20,7 +20,6 @@ import { PublicCategorie } from '../../enum/public.enum'; import { Category } from '../../models/category.model'; import { Module } from '../../models/module.model'; import { SearchService } from '../../services/search.service'; - @Component({ selector: 'app-structure-details', templateUrl: './structure-details.component.html', @@ -85,8 +84,8 @@ export class StructureDetailsComponent implements OnInit { private tclService: TclService, private profileService: ProfileService, private authService: AuthService, - private route: ActivatedRoute, private parametersService: ParametersService, + private route: ActivatedRoute, private location: Location, private router: Router ) { diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts index 59eb0ea107d46dcd15a9e329b1ce114684d1801b..0689a84b96c130c6676e34a4272d83a943e8fc79 100644 --- a/src/app/structure-list/services/search.service.ts +++ b/src/app/structure-list/services/search.service.ts @@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { SearchResults } from '../../annuaire/models/searchQuery.model'; +import { SearchQuery, SearchResults } from '../../annuaire/models/searchQuery.model'; import { Category } from '../models/category.model'; import { Module } from '../models/module.model'; @@ -10,6 +10,9 @@ import { Module } from '../models/module.model'; providedIn: 'root', }) export class SearchService { + public annuaireSearchQuery: SearchQuery; + public checkedFilterList: string[] = []; + constructor(private http: HttpClient) {} public getCategoriesTraining(): Observable<Category[]> { diff --git a/src/app/utils/CustomRegExp.ts b/src/app/utils/CustomRegExp.ts index 65ab1a30c1a6f44cb0b95e0a2a824fd173214591..68317997e5fae1446e0254f80247c84392212201 100644 --- a/src/app/utils/CustomRegExp.ts +++ b/src/app/utils/CustomRegExp.ts @@ -17,7 +17,7 @@ export class CustomRegExp { /** * Validate an email */ - public static readonly EMAIL: RegExp = /^[a-z0-9.\-_]+@[a-z0-9.-]+[.][a-z]{2,3}/; //NOSONAR + public static readonly EMAIL: RegExp = /^[a-z0-9.\-_]+@[a-z0-9.-]+[.][a-z]{2,3}$/; //NOSONAR public static readonly TEXT_WITHOUT_NUMBER: RegExp = /^[A-Za-zÀ-ÖØ-öø-ÿ- ]{1,}$/; //NOSONAR /** * Validate a phone number (4 or 10 digits, allowing spaces, dashes and dots as spacers)