Commit 4aa542f7 authored by Jérémie BRISON's avatar Jérémie BRISON Committed by Hugo SUBTIL
Browse files

feat: structure form edit + data display refacto

parent 525ab88d
This diff is collapsed.
......@@ -20,6 +20,7 @@ import { ModalFilterComponent } from './structure-list/components/modal-filter/m
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
import { AboutComponent } from './about/about.component';
import { MenuPhoneComponent } from './menu-phone/menu-phone.component';
import { FormComponent } from './form/form.component';
import { UserVerificationComponent } from './user-verification/user-verification.component';
import { AuthGuard } from './guards/auth.guard';
import { CustomHttpInterceptor } from './config/http-interceptor';
......@@ -40,6 +41,7 @@ import { ProfileModule } from './profile/profile.module';
LegalNoticeComponent,
AboutComponent,
MenuPhoneComponent,
FormComponent,
UserVerificationComponent,
],
imports: [BrowserModule, HttpClientModule, AppRoutingModule, SharedModule, MapModule, ProfileModule],
......
<form [formGroup]="structureForm" *ngIf="structureForm" (ngSubmit)="onSubmit(structureForm)">
<p>Votre structure est-elle ?*</p>
<input type="radio" formControlName="structureRepresentation" value="principal" /> Un établissement principal (siège
social)<br />
<input type="radio" formControlName="structureRepresentation" value="antenne" /> Une permanence (antenne)
<app-validator-form [control]="getStructureControl('structureRepresentation')"></app-validator-form>
<p>Nom de votre structure*</p>
<input type="text" formControlName="structureName" />
<app-validator-form [control]="getStructureControl('structureName')"></app-validator-form>
<p>Type de structure*</p>
<div *ngFor="let choice of typeStructure | keyvalue">
<label>
<input
type="checkbox"
[value]="choice.key"
(change)="onCheckChange($event, 'structureType')"
[checked]="isInArray(choice.key, 'structureType')"
/>
{{ choice.value }}
</label>
</div>
<app-validator-form [control]="getStructureControl('structureType')"></app-validator-form>
<p>Démarche</p>
<div *ngIf="proceduresAccompaniment">
<p>{{ proceduresAccompaniment.name }}</p>
<div *ngFor="let module of proceduresAccompaniment.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, proceduresAccompaniment.id)"
[checked]="isInArray(module.id, proceduresAccompaniment.id)"
/>
{{ module.text }}
</label>
</div>
</div>
<p>Description</p>
<textarea rows="4" style="width: 100%" maxlength="500" formControlName="description"></textarea>
<p>
Afin de rendre visible l'offre de formation numérique proposée lors de ce nouveau confinement, merci d'indiquer ici,
les activités que vous avez pu maintenir
</p>
<textarea rows="4" style="width: 100%" maxlength="1000" formControlName="lockdownActivity"></textarea>
<div formGroupName="address">
<p>ADRESSE</p>
<p>Numéro</p>
<input type="text" autocomplete="street-address" formControlName="numero" />
<p>Voie*</p>
<input type="text" formControlName="street" />
<app-validator-form [control]="getAddressControl('street')"></app-validator-form>
<p>Commune*</p>
<input type="text" formControlName="commune" />
<app-validator-form [control]="getAddressControl('commune')"></app-validator-form>
</div>
<p>VOUS JOINDRE</p>
<p>Téléphone*</p>
<input type="text" formControlName="contactPhone" />
<app-validator-form [control]="getStructureControl('contactPhone')"></app-validator-form>
<p>Courriel*</p>
<input type="email" formControlName="contactMail" />
<app-validator-form [control]="getStructureControl('contactMail')"></app-validator-form>
<p>Site web</p>
<input type="text" formControlName="website" />
<p>Présence sur les réseaux sociaux</p>
<p>Facebook</p>
<input type="text" formControlName="facebook" />
<p>Twitter</p>
<input type="text" formControlName="twitter" />
<p>Instagram</p>
<input type="text" formControlName="instagram" />
<p>Personne à contacter</p>
<p>Civilité</p>
<input type="radio" formControlName="gender" value="Madame" />Madame <br />
<input type="radio" formControlName="gender" value="Monsieur" />Monsieur
<p>Nom</p>
<input type="text" formControlName="contactName" />
<p>Prénom</p>
<input type="text" formControlName="contactSurname" />
<p>Courriel*</p>
<input type="email" formControlName="contactMail" />
<app-validator-form [control]="getStructureControl('contactMail')"></app-validator-form>
<p>Fonction</p>
<select formControlName="fonction">
<option value="">---Sélectionner---</option>
<option *ngFor="let fonction of fonctions | keyvalue" [value]="fonction.key">
{{ fonction.value }}
</option>
</select>
<p>Accessibilité</p>
<input type="checkbox" formControlName="pmrAccess" />Accessibilité personnes à mobilité réduite (PMR) <br />
<div *ngIf="accessModality">
<p>{{ accessModality.name }}*</p>
<div *ngFor="let module of accessModality.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, accessModality.id)"
[checked]="isInArray(module.id, accessModality.id)"
/>
{{ module.text }}
</label>
</div>
<app-validator-form [control]="getStructureControl('accessModality')"></app-validator-form>
</div>
<p>Pour les RDV, merci de préciser s'il est nécessaire d'apporter des pièces justificatives ou du matériel.</p>
<textarea rows="4" style="width: 100%" maxlength="500" formControlName="documentsMeeting"></textarea>
<div *ngIf="labelsQualifications">
<p>{{ labelsQualifications.name }}</p>
<div *ngFor="let module of labelsQualifications.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, labelsQualifications.id)"
[checked]="isInArray(module.id, labelsQualifications.id)"
/>
{{ module.text }}
</label>
</div>
</div>
<div *ngIf="publics">
<p>{{ publics.name }}*</p>
<div *ngFor="let module of publics.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, publics.id)"
[checked]="isInArray(module.id, publics.id)"
/>
{{ module.text }}
</label>
</div>
<app-validator-form [control]="getStructureControl('publics')"></app-validator-form>
</div>
<div formGroupName="hours">
<p>Heures</p>
<div *ngFor="let day of weekDay | keyvalue">
<div [formGroupName]="day.key">
<p>Ouvert le {{ day.value }} ? :</p>
<input type="radio" formControlName="open" (click)="addTime(day.key)" [value]="true" />Oui <br />
<input type="radio" formControlName="open" (click)="removeTime(day.key)" [value]="false" />Non
<div formArrayName="time" *ngIf="isOpen(day.key)">
<div *ngFor="let time of getTime(day.key).controls; index as i">
<div [formGroupName]="i">
<input type="number" formControlName="openning" />
<input type="number" formControlName="closing" />
</div>
<div *ngIf="i < 1">
<input
type="checkbox"
[value]="false"
(change)="onCheckPlageHoursChange($event, day.key, time)"
[checked]="getTime(day.key).controls.length == 2"
/>Ajouter une plage
</div>
</div>
</div>
</div>
</div>
</div>
<p>Fermetures exceptionnelles</p>
<input type="text" formControlName="exceptionalClosures" />
<div *ngIf="publicsAccompaniment">
<p>{{ publicsAccompaniment.name }}</p>
<div *ngFor="let module of publicsAccompaniment.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, publicsAccompaniment.id)"
[checked]="isInArray(module.id, publicsAccompaniment.id)"
/>
{{ module.text }}
</label>
</div>
</div>
<p>Formations au numérique proposées</p>
<p>
Ces modules de compétences sont issus du référentiel national et identifiés dans le cadre du déploiement du Pass
numérique sur la Métropole (pour en savoir +)
</p>
<div *ngFor="let c of categoryTraining">
<p>{{ c.name }}</p>
<div *ngFor="let module of c.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, c.id)"
[checked]="isInArray(module.id, c.id)"
/>
{{ module.text }}
</label>
</div>
</div>
<div *ngIf="equipmentsAndServices">
<p>{{ equipmentsAndServices.name }}</p>
<div *ngFor="let module of equipmentsAndServices.modules">
<label>
<input
type="checkbox"
[value]="module.id"
(change)="onCheckChange($event, equipmentsAndServices.id)"
[checked]="isInArray(module.id, equipmentsAndServices.id)"
/>
{{ module.text }}
</label>
<div *ngIf="isInArray(module.id, equipmentsAndServices.id)">
<div *ngIf="module.id == 'ordinateurs'">
<span>Nombre</span>
<input type="number" formControlName="nbComputers" />
</div>
<div *ngIf="module.id == 'tablettes'">
<span>Nombre</span>
<input type="number" formControlName="nbTablets" />
</div>
<div *ngIf="module.id == 'bornesNumeriques'">
<span>Nombre</span>
<input type="number" formControlName="nbNumericTerminal" />
</div>
<div *ngIf="module.id == 'imprimantes'">
<span>Nombre</span>
<input type="number" formControlName="nbPrinters" />
</div>
</div>
</div>
</div>
<p>Précisions si nécessaire</p>
<textarea rows="4" style="width: 100%" maxlength="500" formControlName="equipmentsDetails"></textarea>
<p>L'accès à ce matériel est</p>
<div *ngFor="let equipment of equipmentAccess | keyvalue">
<label>
<input
type="checkbox"
[value]="equipment.key"
(change)="onCheckChange($event, 'equipmentsAccessType')"
[checked]="isInArray(equipment.key, 'equipmentsAccessType')"
/>
{{ equipment.value }}
</label>
</div>
<br />
<button type="submit" [disabled]="structureForm.invalid">OK</button>
</form>
form {
position: fixed;
background: white;
width: 100vh;
height: 100vh;
top: 0;
z-index: 9999;
overflow: auto;
}
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
import { Time } from '../models/time.model';
import { FormComponent } from './form.component';
fdescribe('FormComponent', () => {
let component: FormComponent;
let fixture: ComponentFixture<FormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FormComponent],
imports: [HttpClientTestingModule],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.structureForm = new FormGroup({
structureType: new FormArray([new FormControl('mediatheque'), new FormControl('cyber')]),
structureName: new FormControl('structure.structureName', Validators.required),
structureRepresentation: new FormControl('structure.structureRepresentation', Validators.required),
description: new FormControl('structure.description'),
lockdownActivity: new FormControl('structure.lockdownActivity'),
address: new FormGroup({
numero: new FormControl('structure.address.numero'),
street: new FormControl('structure.address.street', Validators.required),
commune: new FormControl('structure.address.commune', Validators.required),
}),
contactPhone: new FormControl('structure.contactPhone', Validators.required),
contactMail: new FormControl('structure.contactMail', Validators.required),
website: new FormControl('structure.website'),
facebook: new FormControl('structure.facebook'),
twitter: new FormControl('structure.twitter'),
instagram: new FormControl('structure.instagram'),
gender: new FormControl('structure.gender'),
contactName: new FormControl('structure.contactName'),
contactSurname: new FormControl('structure.contactSurname'),
fonction: new FormControl('structure.fonction'),
pmrAccess: new FormControl('structure.pmrAccess'),
documentsMeeting: new FormControl('structure.documentsMeeting'),
hours: new FormGroup({
monday: new FormGroup({
open: new FormControl(true, Validators.required),
time: new FormArray([
new FormGroup({
openning: new FormControl(900, Validators.required),
closing: new FormControl(1200, Validators.required),
}),
]),
}),
tuesday: new FormGroup({
open: new FormControl(true, Validators.required),
time: new FormArray([]) as FormArray,
}),
wednesday: new FormGroup({
open: new FormControl(true, Validators.required),
time: new FormArray([]) as FormArray,
}),
thursday: new FormGroup({
open: new FormControl(true, Validators.required),
time: new FormArray([]) as FormArray,
}),
friday: new FormGroup({
open: new FormControl(true, Validators.required),
time: new FormArray([]) as FormArray,
}),
saturday: new FormGroup({
open: new FormControl(false, Validators.required),
time: new FormArray([]) as FormArray,
}),
sunday: new FormGroup({
open: new FormControl(false, Validators.required),
time: new FormArray([]) as FormArray,
}),
}),
exceptionalClosures: new FormControl('structure.exceptionalClosures'),
labelsQualifications: new FormControl([]),
accessModality: new FormControl([]),
publicsAccompaniment: new FormControl([]),
equipmentsAndServices: new FormControl([]),
publics: new FormControl([]),
baseSkills: new FormControl([]),
accessRight: new FormControl([]),
parentingHelp: new FormControl([]),
socialAndProfessional: new FormControl([]),
digitalCultureSecurity: new FormControl([]),
nbComputers: new FormControl('structure.nbComputers'),
nbPrinters: new FormControl('structure.nbPrinters'),
nbTablets: new FormControl('structure.nbTablets'),
nbNumericTerminal: new FormControl('structure.nbNumericTerminal'),
equipmentsDetails: new FormControl('structure.equipmentsDetails'),
equipmentsAccessType: new FormControl([]),
});
});
it('should return the correct Abstract Control', () => {
const nameControl = 'structureName';
const control = component.getStructureControl(nameControl);
const expectControl = component.structureForm.get(nameControl);
expect(control).toEqual(expectControl);
});
it('should return the correct Abstract Control from address', () => {
const nameControl = 'street';
const control = component.getAddressControl(nameControl);
const addressForm = component.structureForm.get('address').get(nameControl);
expect(control).toEqual(addressForm);
});
it('should return the correct Time from a specific day', () => {
const day = 'monday';
const control = component.getTime(day);
const TimeForm = component.structureForm.get('hours').get(day).get('time') as FormArray;
expect(control).toEqual(TimeForm);
});
it('should return true', () => {
const day = 'monday';
const control = component.isOpen(day);
expect(control).toEqual(true);
});
it('should return check if value is in formArray', () => {
const nameControl = 'structureType';
const isInArray = component.isInArray('cyber', nameControl);
const isntInArray = component.isInArray('unknowType', nameControl);
expect(isInArray).toEqual(true);
expect(isntInArray).toEqual(false);
});
});
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { AbstractControl, FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
import { Structure } from '../models/structure.model';
import { Time } from '../models/time.model';
import { Day } from '../models/day.model';
import { StructureService } from '../services/structure.service';
import { SearchService } from '../structure-list/services/search.service';
import { Category } from '../structure-list/models/category.model';
import { CategoryEnum } from '../shared/enum/category.enum';
import { EquipmentAccess } from '../shared/enum/equipmentAccess.enum';
import { WeekDayEnum } from '../shared/enum/weekDay.enum';
import { typeStructureEnum } from '../shared/enum/typeStructure.enum';
import { FonctionContactEnum } from '../shared/enum/fonctionContact.enum';
@Component({
selector: 'app-structureForm',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss'],
})
export class FormComponent implements OnInit {
@Input() public idStructure: number;
@Output() closeEvent = new EventEmitter<Structure>();
public structureForm: FormGroup;
public equipmentAccess = EquipmentAccess;
public weekDay = WeekDayEnum;
public typeStructure = typeStructureEnum;
public fonctions = FonctionContactEnum;
public categoryTraining: Category[];
public labelsQualifications: Category;
public publics: Category;
public accessModality: Category;
public publicsAccompaniment: Category;
public equipmentsAndServices: Category;
public proceduresAccompaniment: Category;
public structureId: number;
constructor(private structureService: StructureService, private searchService: SearchService) {}
ngOnInit(): void {
this.structureService.getStructure(this.idStructure).subscribe((structure) => {
this.initForm(structure);
this.structureId = structure.id;
});
this.searchService.getCategoriesAccompaniment().subscribe((categories: Category[]) => {
this.proceduresAccompaniment = categories[0];
});
this.searchService.getCategoriesMoreFilters().subscribe((categories: Category[]) => {
categories.forEach((categ) => {
switch (categ.id) {
case CategoryEnum.accessModality: {
this.accessModality = categ;
break;
}
case CategoryEnum.equipmentsAndServices: {
this.equipmentsAndServices = categ;
break;
}
case CategoryEnum.labelsQualifications: {
this.labelsQualifications = categ;
break;
}
case CategoryEnum.publics: {
this.publics = categ;
break;
}
case CategoryEnum.publicsAccompaniment: {
this.publicsAccompaniment = categ;
break;
}
}
});
});
this.searchService.getCategoriesTraining().subscribe((t) => {
this.categoryTraining = t;
});
}
private initForm(structure: Structure): void {
// Init form
this.structureForm = new FormGroup({
structureType: this.loadArrayForCheckbox(structure.structureType, true),
structureName: new FormControl(structure.structureName, Validators.required),
structureRepresentation: new FormControl(structure.structureRepresentation, Validators.required),
description: new FormControl(structure.description),
lockdownActivity: new FormControl(structure.lockdownActivity),
address: new FormGroup({
numero: new FormControl(structure.address.numero),
street: new FormControl(structure.address.street, Validators.required),
commune: new FormControl(structure.address.commune, Validators.required),
}),
contactPhone: new FormControl(structure.contactPhone, [Validators.required, Validators.pattern('[0-9]{10}')]),
contactMail: new FormControl(structure.contactMail, [
Validators.required,
Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$'),
]),
website: new FormControl(structure.website),
facebook: new FormControl(structure.facebook),
twitter: new FormControl(structure.twitter),
instagram: new FormControl(structure.instagram),
gender: new FormControl(structure.gender),
contactName: new FormControl(structure.contactName),
contactSurname: new FormControl(structure.contactSurname),
fonction: new FormControl(structure.fonction),
pmrAccess: new FormControl(structure.pmrAccess),
documentsMeeting: new FormControl(structure.documentsMeeting),
hours: new FormGroup({
monday: this.createDay(structure.hours.monday),
tuesday: this.createDay(structure.hours.tuesday),
wednesday: this.createDay(structure.hours.wednesday),
thursday: this.createDay(structure.hours.thursday),
friday: this.createDay(structure.hours.friday),
saturday: this.createDay(structure.hours.saturday),
sunday: this.createDay(structure.hours.sunday),
}),
exceptionalClosures: new FormControl(structure.exceptionalClosures),
labelsQualifications: this.loadArrayForCheckbox(structure.labelsQualifications, false),
accessModality: this.loadArrayForCheckbox(structure.accessModality, true),
publicsAccompaniment: this.loadArrayForCheckbox(structure.publicsAccompaniment, false),
proceduresAccompaniment: this.loadArrayForCheckbox(structure.proceduresAccompaniment, false),
equipmentsAndServices: this.loadArrayForCheckbox(structure.equipmentsAndServices, false),
publics: this.loadArrayForCheckbox(structure.publics, true),
baseSkills: this.loadArrayForCheckbox(structure.baseSkills, false),
accessRight: this.loadArrayForCheckbox(structure.accessRight, false),
parentingHelp: this.loadArrayForCheckbox(structure.parentingHelp, false),
socialAndProfessional: this.loadArrayForCheckbox(structure.socialAndProfessional, false),
digitalCultureSecurity: this.loadArrayForCheckbox(structure.digitalCultureSecurity, false),
nbComputers: new FormControl(structure.equipmentsAndServices.includes('ordinateurs') ? structure.nbComputers : 0),
nbPrinters: new FormControl(structure.equipmentsAndServices.includes('imprimantes') ? structure.nbPrinters : 0),
nbTablets: new FormControl(structure.equipmentsAndServices.includes('tablettes') ? structure.nbTablets : 0),
nbNumericTerminal: new FormControl(
structure.equipmentsAndServices.includes('bornesNumeriques') ? structure.nbNumericTerminal : 0
),
equipmentsDetails: new FormControl(structure.equipmentsDetails),
equipmentsAccessType: this.loadArrayForCheckbox(structure.equipmentsAccessType, false),
});
}
private loadArrayForCheckbox(array: string[], isRequired: boolean): FormArray {
return new FormArray(
array.map((str) => new FormControl(str)),
isRequired ? Validators.required : Validators.nullValidator
);
}
public getStructureControl(nameControl: string): AbstractControl {
return this.structureForm.get(nameControl);
}
public getAddressControl(nameControl: string): AbstractControl {
return this.structureForm.get('address').get(nameControl);
}
public getTime(day: string): FormArray {
return this.structureForm.get('hours').get(day).get('time') as FormArray;
}
public isOpen(day: string): boolean {
return this.structureForm.get('hours').get(day).get('open').value;
}
private createDay(day: Day): FormGroup {
return new FormGroup({
open: new FormControl(day.open, Validators.required),
time: new FormArray(day.time.map((oneTime) => this.createTime(oneTime))) as FormArray,
});
}
private createTime(time: Time): FormGroup {
return new FormGroup({
openning: new FormControl(time.openning, Validators.required),
closing: new FormControl(time.closing, Validators.required),
});
}
public addTime(day: string): void {
if (!this.structureForm.get('hours').get(day).value.open) {
this.getTime(day).push(this.createTime(new Time()));
}
}