diff --git a/src/frontend/app/administration/administration.module.ts b/src/frontend/app/administration/administration.module.ts
index 820a9ef3a6da3edf7a8553890155532d9c5b99b9..f35bd496b960eb3315c14ce1c41498dce49d09f3 100755
--- a/src/frontend/app/administration/administration.module.ts
+++ b/src/frontend/app/administration/administration.module.ts
@@ -2,10 +2,6 @@ import { NgModule }                             from '@angular/core';
 
 import { SharedModule }                         from '../app-common.module';
 
-//import { MenuComponent }                        from '../menu/menu.component';
-//import { MenuNavComponent }                     from '../menu/menu-nav.component';
-//import { MenuTopComponent }                     from '../menu/menu-top.component';
-
 import { AdministrationRoutingModule }          from './administration-routing.module';
 
 import { AdministrationComponent }                      from './home/administration.component';
@@ -63,9 +59,6 @@ import { ContactsPageAdministrationComponent }              from './contact/page
         AdministrationRoutingModule
     ],
     declarations: [
-        //MenuComponent,
-        //MenuNavComponent,
-        //MenuTopComponent,
         AdministrationComponent,
         UsersAdministrationComponent,
         UserAdministrationComponent,
diff --git a/src/frontend/app/administration/contact/modal/contact-modal.component.html b/src/frontend/app/administration/contact/modal/contact-modal.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..68857ae59061ee5950ca50d9c0f1eb48528703b2
--- /dev/null
+++ b/src/frontend/app/administration/contact/modal/contact-modal.component.html
@@ -0,0 +1,10 @@
+<h1 mat-dialog-title>
+    <span style="flex: 1;">
+        content
+    </span>
+    <button [title]="lang.close" mat-icon-button (click)="dialogRef.close();">
+        <mat-icon class="fa fa-times"></mat-icon>
+    </button></h1>
+<mat-dialog-content class="modal-container">
+    <app-contact-form (onSubmitEvent)="dialogRef.close($event)"></app-contact-form>
+</mat-dialog-content>
\ No newline at end of file
diff --git a/src/frontend/app/administration/contact/modal/contact-modal.component.scss b/src/frontend/app/administration/contact/modal/contact-modal.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a3b61021e192c6a2fc9351c568f31a1a1aedf6e4
--- /dev/null
+++ b/src/frontend/app/administration/contact/modal/contact-modal.component.scss
@@ -0,0 +1,15 @@
+@import '../../../../css/vars.scss';
+
+.mat-dialog-title {
+    padding: 10px;
+    display: flex;
+    align-items: center;
+}
+.modal-container{
+    min-height: 250px;
+    height: auto;
+}
+
+.modal-body{
+    min-height: auto;
+}
diff --git a/src/frontend/app/administration/contact/modal/contact-modal.component.ts b/src/frontend/app/administration/contact/modal/contact-modal.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..edb6e9cc77fc3db4c92ae912e870031662e050fd
--- /dev/null
+++ b/src/frontend/app/administration/contact/modal/contact-modal.component.ts
@@ -0,0 +1,20 @@
+import { Component, Inject } from '@angular/core';
+import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { LANG } from '../../../translate.component';
+import { HttpClient } from '@angular/common/http';
+
+@Component({
+    templateUrl: 'contact-modal.component.html',
+    styleUrls: ['contact-modal.component.scss'],
+})
+export class ContactModalComponent {
+    lang: any = LANG;
+
+    constructor(
+        public http: HttpClient,
+        @Inject(MAT_DIALOG_DATA) public data: any,
+        public dialogRef: MatDialogRef<ContactModalComponent>) {
+    }
+
+    ngOnInit(): void { }
+}
diff --git a/src/frontend/app/administration/contact/page/contacts-page-administration.component.html b/src/frontend/app/administration/contact/page/contacts-page-administration.component.html
index 3def2a46acf76455c2b05f747015cb81cb0318aa..1e69337cc666b033c70e0ee9307f549d479e9bd7 100644
--- a/src/frontend/app/administration/contact/page/contacts-page-administration.component.html
+++ b/src/frontend/app/administration/contact/page/contacts-page-administration.component.html
@@ -28,243 +28,7 @@
         </div>
         <div class="container" [class.fullContainer]="appService.getViewMode()">
             <div class="container-content">
-                <div class="loading" *ngIf="loading; else elseTemplate">
-                    <mat-spinner style="margin:auto;"></mat-spinner>
-                </div>
-                <ng-template #elseTemplate>
-                    <mat-menu #menu="matMenu">
-                        <button mat-menu-item [matMenuTriggerFor]="mainInfo"
-                            [disabled]="noField('mainInfo')">{{lang.denomination}}</button>
-                        <button mat-menu-item [matMenuTriggerFor]="address"
-                            [disabled]="noField('address')">{{lang.address}}</button>
-                        <button mat-menu-item [matMenuTriggerFor]="complement"
-                            [disabled]="noField('complement')">{{lang.additionals}}</button>
-                    </mat-menu>
-
-                    <mat-menu #mainInfo="matMenu">
-                        <button mat-menu-item (click)="toogleAllFieldsUnit('mainInfo')"
-                            style="text-align: center;">{{lang.addAll}}</button>
-                        <mat-divider></mat-divider>
-                        <ng-container *ngFor="let field of contactForm">
-                            <button mat-menu-item *ngIf="!field.display && field.unit === 'mainInfo'"
-                                (click)="field.display=!field.display">
-                                <mat-icon *ngIf="field.filling" style="height: auto;padding-right: 10px;" [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
-                                <span>{{field.label}}</span>
-                            </button>
-                        </ng-container>
-                    </mat-menu>
-
-                    <mat-menu #address="matMenu">
-                        <button mat-menu-item (click)="toogleAllFieldsUnit('address')"
-                            style="text-align: center;">{{lang.addAll}}</button>
-                        <mat-divider></mat-divider>
-                        <ng-container *ngFor="let field of contactForm">
-                            <button mat-menu-item *ngIf="!field.display && field.unit === 'address'"
-                                (click)="field.display=!field.display">
-                                <mat-icon *ngIf="field.filling" style="height: auto;padding-right: 10px;" [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
-                                <span>{{field.label}}</span>
-                            </button>
-                        </ng-container>
-                    </mat-menu>
-                    <mat-menu #complement="matMenu">
-                        <button mat-menu-item (click)="toogleAllFieldsUnit('complement')"
-                            style="text-align: center;">{{lang.addAll}}</button>
-                        <mat-divider></mat-divider>
-                        <ng-container *ngFor="let field of contactForm">
-                            <button mat-menu-item *ngIf="!field.display && field.unit === 'complement'"
-                                (click)="field.display=!field.display">
-                                <mat-icon *ngIf="field.filling" style="height: auto;padding-right: 10px;" [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
-                                <span>{{field.label}}</span>
-                            </button>
-                        </ng-container>
-                    </mat-menu>
-                    <div style="padding: 10px;">
-                        <div class="rate_{{fillingRate.class}}" >{{lang.contactFilledTo}} <b>{{fillingRate.value}} %</b></div>
-                        <mat-progress-bar mode="determinate" class="fillingBar" [color]="fillingRate.class" [value]="fillingRate.value"></mat-progress-bar>
-                        
-                    </div>
-                    <div [class.multipleUnits]="!isEmptyUnit('address') || !isEmptyUnit('complement')">
-                        <ng-container *ngFor="let unit of contactUnit">
-                            <div *ngIf="!isEmptyUnit(unit.id)">
-                                <mat-list>
-                                    <h3 mat-subheader class="unitTitle"><span style="flex:1">{{unit.label}}</span><a
-                                            *ngIf="unit.id === 'address'" (click)="addressBANMode=!addressBANMode"
-                                            style="cursor: pointer;">{{addressBANMode ? lang.switchManualAddress : lang.searchAddressDb}}</a>
-                                    </h3>
-                                    <ng-container *ngFor="let field of contactForm;let i=index">
-                                        <mat-list-item class="contact-item"
-                                            *ngIf="(field.unit === unit.id && unit.id !== 'address') || (field.unit === unit.id && unit.id === 'address' && !addressBANMode)">
-                                            <p mat-line class="contact-content" *ngIf="field.display">
-                                                <ng-container *ngIf="field.type === 'string'">
-                                                    <mat-form-field>
-                                                        <input matInput [formControl]="field.control"
-                                                            [placeholder]="field.label" (blur)="checkCompany(field);checkFilling();"
-                                                            [required]="field.required">
-                                                        <mat-hint
-                                                            *ngIf="companyFound !== null && field.id === 'company'"
-                                                            align="end">{{lang.contactsParameters_company}} <b>{{companyFound.company}}</b>
-                                                            {{lang.found}}
-                                                            !
-                                                            cliquez <a (click)="setAddress(companyFound)"
-                                                                style="cursor: pointer;font-weight:bold;">{{lang.here}}</a>
-                                                            {{lang.toCopyAddress}}</mat-hint>
-                                                        <mat-error *ngIf="field.control.status!=='VALID'  && field.control.touched">
-                                                            {{getErrorMsg(field.control.errors)}}</mat-error>
-                                                        <mat-icon style="height: auto;" matSuffix [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
-                                                    </mat-form-field>
-                                                </ng-container>
-                                                <ng-container *ngIf="field.type === 'integer'">
-                                                    <mat-form-field>
-                                                        <input type="text" matInput [formControl]="field.control"
-                                                            [placeholder]="field.label" min="0" step="0.1"
-                                                            [required]="field.required">
-                                                        <mat-error *ngIf="field.control.status!=='VALID' && field.control.touched">
-                                                            {{getErrorMsg(field.control.errors)}}</mat-error>
-                                                    </mat-form-field>
-                                                </ng-container>
-                                                <ng-container *ngIf="field.type === 'select'">
-                                                    <plugin-select-search [label]="field.label" [showLabel]="true"
-                                                        [formControlSelect]="field.control"
-                                                        [placeholderLabel]="field.label" [datas]="field.values"
-                                                        [class]="''">
-                                                    </plugin-select-search>
-                                                </ng-container>
-                                                <ng-container *ngIf="field.type === 'date'">
-                                                    <mat-form-field (click)="picker.open()" style="cursor:pointer;">
-                                                        <mat-label>{{field.label}}
-                                                        </mat-label>
-                                                        <input [formControl]="field.control" matInput
-                                                            [matDatepicker]="picker" [placeholder]="field.label"
-                                                            readonly style="cursor:pointer;">
-                                                        <mat-datepicker-toggle matSuffix [for]="picker"
-                                                            *ngIf="!field.control.value">
-                                                        </mat-datepicker-toggle>
-                                                        <mat-datepicker [touchUi]="appService.getViewMode()" #picker>
-                                                        </mat-datepicker>
-                                                        <button mat-button color="warn" matSuffix mat-icon-button
-                                                            *ngIf="field.control.value && !field.control.disabled"
-                                                            (click)="$event.stopPropagation();field.control.reset();"
-                                                            [title]="lang.eraseValue">
-                                                            <mat-icon color="warn" class="fa fa-calendar-times">
-                                                            </mat-icon>
-                                                        </button>
-                                                    </mat-form-field>
-                                                </ng-container>
-                                                <ng-container *ngIf="field.type === 'radio'">
-                                                    <mat-radio-group class="radio-form" color="primary"
-                                                        [formControl]="field.control">
-                                                        <mat-radio-button *ngFor="let value of field.values"
-                                                            [value]="value.id">
-                                                            {{value.label}}
-                                                        </mat-radio-button>
-                                                    </mat-radio-group>
-                                                </ng-container>
-                                                <ng-container *ngIf="field.type === 'checkbox'">
-                                                    <mat-selection-list #shoes class="checkbox-form"
-                                                        [formControl]="field.control">
-                                                        <mat-list-option *ngFor="let value of field.values"
-                                                            [value]="value.id" color="primary"
-                                                            checkboxPosition="before">
-                                                            {{value.label}}
-                                                        </mat-list-option>
-                                                    </mat-selection-list>
-                                                </ng-container>
-                                            </p>
-                                            <button *ngIf="field.display" [disabled]="!canDelete(field)" mat-icon-button matSuffix
-                                                color="warn" (click)="removeField(field)">
-                                                <mat-icon class="fa fa-trash"></mat-icon>
-                                            </button>
-                                        </mat-list-item>
-                                        <ng-container
-                                            *ngIf="unit.id === 'address' && addressBANMode && ['addressAdditional1', 'addressAdditional2'].indexOf(field.id) > -1">
-                                            <mat-list-item class="contact-item">
-                                                <p mat-line class="contact-content" *ngIf="field.display">
-                                                    <mat-form-field>
-                                                        <input matInput [formControl]="field.control"
-                                                            [placeholder]="field.label" [required]="field.required">
-                                                        <mat-error *ngIf="field.control.hasError('required')">
-                                                            {{lang.requiredField}}</mat-error>
-                                                    </mat-form-field>
-                                                </p>
-                                                <button *ngIf="field.display" [disabled]="!canDelete(field)" mat-icon-button
-                                                    matSuffix color="warn" (click)="removeField(field)">
-                                                    <mat-icon class="fa fa-trash"></mat-icon>
-                                                </button>
-                                            </mat-list-item>
-                                        </ng-container>
-                                        <ng-container *ngIf="unit.id === 'address' && addressBANMode && i === 0">
-                                            <mat-list-item>
-                                                <p mat-line class="contact-content">
-                                                    <mat-form-field appearance='outline' class="smallInput">
-                                                        <button mat-button matSuffix [matMenuTriggerFor]="menuDep"
-                                                            (click)="$event.stopPropagation();"
-                                                            [title]="lang.targetDepartment">
-                                                            {{addressBANCurrentDepartment}}&nbsp;<i
-                                                                class="fa fa-chevron-down"></i>
-                                                        </button>
-                                                        <mat-menu #menuDep="matMenu">
-                                                            <button mat-menu-item *ngFor="let dep of departmentList"
-                                                                (click)="addressBANCurrentDepartment = dep">{{dep}}</button>
-                                                        </mat-menu>
-                                                        <mat-icon color="primary" class="fa fa-search" matPrefix
-                                                            style="font-size: 15px;"></mat-icon>
-                                                        <input type="text" #autoCompleteInput
-                                                            [placeholder]="lang.searchAddressBan" matInput
-                                                            [formControl]="addressBANControl" [matAutocomplete]="auto"
-                                                            (click)="$event.stopPropagation()"
-                                                            (focus)="resetAutocompleteAddressBan()" maxlength="128">
-                                                        <mat-autocomplete #auto="matAutocomplete"
-                                                            (optionSelected)="selectAddressBan($event)">
-                                                            <ng-container
-                                                                *ngIf="addressBANResult.length > 0 && !addressBANLoading">
-                                                                <mat-option
-                                                                    *ngFor="let addressBANResult of addressBANFilteredResult | async"
-                                                                    [value]="addressBANResult">
-                                                                    {{addressBANResult.address}}
-                                                                </mat-option>
-                                                            </ng-container>
-                                                            <mat-option class="autoCompleteInfoResult smallInputInfo"
-                                                                *ngIf="addressBANResult.length === 0 && !addressBANLoading"
-                                                                disabled [innerHTML]="addressBANInfo">
-                                                            </mat-option>
-                                                            <mat-option *ngIf="addressBANLoading" disabled>
-                                                                <mat-spinner diameter="20"></mat-spinner>
-                                                            </mat-option>
-                                                        </mat-autocomplete>
-                                                    </mat-form-field>
-                                                    <mat-card style="margin:10px;" *ngIf="!emptyAddress()">
-                                                        <mat-list-item class="contact-address" (click)="goTo(contact)"
-                                                            [title]="lang.address">
-                                                            <mat-icon mat-list-icon color="primary"
-                                                                class="contact-group fas fa-map-marker-alt"></mat-icon>
-                                                            <p mat-line class="contact-content">
-                                                                {{getValue('addressNumber')}}
-                                                                {{getValue('addressStreet')}}
-                                                            </p>
-                                                            <p mat-line class="contact-content">
-                                                                {{getValue('addressPostcode')}}
-                                                                {{getValue('addressTown')}}
-                                                            </p>
-                                                            <p mat-line class="contact-content">
-                                                                {{getValue('addressCountry')}} </p>
-                                                        </mat-list-item>
-                                                    </mat-card>
-                                                </p>
-                                            </mat-list-item>
-                                        </ng-container>
-                                    </ng-container>
-                                </mat-list>
-                            </div>
-                        </ng-container>
-                    </div>
-                    <div style="text-align:center;">
-                        <button mat-raised-button color="default" type="button"
-                            [matMenuTriggerFor]="menu">{{lang.moreInfos}}...</button>
-
-                        <button mat-raised-button color="primary" type="button"
-                            (click)="onSubmit()">{{lang.validate}}</button>
-                    </div>
-                </ng-template>
+                <app-contact-form *ngIf="!loading" [creationMode]="creationMode" [contactId]="contactId" (onSubmitEvent)="goToList()"></app-contact-form>
             </div>
         </div>
     </mat-sidenav-content>
diff --git a/src/frontend/app/administration/contact/page/contacts-page-administration.component.scss b/src/frontend/app/administration/contact/page/contacts-page-administration.component.scss
index 23cec77a17d6033dced3a3ceb955110c0886967d..b10a3ef8c289c653453e3c9bb434bf6285a83e95 100644
--- a/src/frontend/app/administration/contact/page/contacts-page-administration.component.scss
+++ b/src/frontend/app/administration/contact/page/contacts-page-administration.component.scss
@@ -3,120 +3,4 @@
 .active, .active:hover , .active:active, .active:focus {
     background-color: $secondary;
     color: white;
-}
-
-.contact-item {
-    height: auto !important;
-}
-
-.multipleUnits div:nth-child(1) {
-    display: inline-grid !important;
-    width: 50%;
-}
-
-.multipleUnits div:nth-child(2) {
-    display: inline-grid !important;
-    width: 50%;
-}
-
-.unitTitle {
-    display: flex;
-    color: $primary;
-}
-
-.contact-address {
-    cursor: pointer;
-    color: #337ab7;
-
-    &:hover {
-        .contact-content {
-            text-decoration: underline;
-        }
-    }
-}
-
-.smallInput {
-    font-size: 11px;
-    padding-left: 20px;
-    padding-right: 20px;
-    .mat-button {
-        width: 30px;
-        height: 25px;
-        color: $primary;
-
-        ::ng-deep.mat-button-wrapper {
-            display: flex;
-            line-height: initial;
-            align-items: center;
-        }
-    }
-    ::ng-deep.mat-form-field-infix {
-        padding : 0px;
-        padding-bottom: 5px;
-    }
-}
-.radio-form {
-    display: flex;
-
-    .mat-radio-button {
-        flex: 1;
-    }
-}
-
-.checkbox-form {
-    overflow: auto;
-    max-height: 200px;
-}
-
-.loading {
-    display: flex;
-    height: 100%;
-}
-
-.fillingBar {
-    ::ng-deep .mat-progress-bar-buffer {
-        background: #E4E8EB;
-    }
-}
-
-.rate_primary {
-    font-size: 10px;
-    text-align: right;
-    color: orange;
-}
-
-.rate_warn {
-    font-size: 10px;
-    text-align: right;
-    color: red;
-}
-
-.rate_accent {
-    font-size: 10px;
-    text-align: right;
-    color: green;
-}
-
-.fillingBar.mat-warn {
-    ::ng-deep.mat-progress-bar-fill::after {
-        background-color: red;
-    }
-}
-
-.fillingBar.mat-primary {
-    ::ng-deep.mat-progress-bar-fill::after {
-        background-color: orange;
-    }
-}
-
-.fillingBar.mat-accent {
-    ::ng-deep.mat-progress-bar-fill::after {
-        background-color: green;
-    }
-}
-
-.mat-error {
-    font-size: 10px;
-    text-align: right;
-    font-weight: bold;
 }
\ No newline at end of file
diff --git a/src/frontend/app/administration/contact/page/contacts-page-administration.component.ts b/src/frontend/app/administration/contact/page/contacts-page-administration.component.ts
index 59a50e98ed7b900fc027c4c442582eaa72f4bc47..9eba00d5a4b0ce1446a5a2ad3ea5dc0b660a901b 100644
--- a/src/frontend/app/administration/contact/page/contacts-page-administration.component.ts
+++ b/src/frontend/app/administration/contact/page/contacts-page-administration.component.ts
@@ -1,15 +1,11 @@
-import { Component, OnInit, ViewChild, EventEmitter } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 import { LANG } from '../../../translate.component';
 import { NotificationService } from '../../../notification.service';
 import { HeaderService } from '../../../../service/header.service';
 import { MatSidenav } from '@angular/material/sidenav';
 import { AppService } from '../../../../service/app.service';
-import { Observable, merge, Subject, of as observableOf, of } from 'rxjs';
-import { MatPaginator, MatSort, MatDialog } from '@angular/material';
-import { takeUntil, startWith, switchMap, map, catchError, filter, exhaustMap, tap, debounceTime, distinctUntilChanged, finalize, count } from 'rxjs/operators';
-import { ConfirmComponent } from '../../../../plugins/modal/confirm.component';
-import { FormControl, Validators, ValidatorFn, FormGroup, FormBuilder } from '@angular/forms';
+import { MatDialog } from '@angular/material';
 import { ActivatedRoute, Router } from '@angular/router';
 
 @Component({
@@ -56,210 +52,17 @@ export class ContactsPageAdministrationComponent implements OnInit {
     
     contactId: number = null;
 
-    contactUnit = [
-        {
-            id: 'mainInfo',
-            label: this.lang.denomination
-        },
-        {
-            id: 'address',
-            label: this.lang.address
-        },
-        {
-            id: 'complement',
-            label: this.lang.additionals
-        }
-    ];
-
-    contactForm: any[] = [
-        {
-            id: 'company',
-            unit: 'mainInfo',
-            label: this.lang.contactsParameters_company,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: true,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'firstname',
-            unit: 'mainInfo',
-            label: this.lang.contactsParameters_firstname,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'lastname',
-            unit: 'mainInfo',
-            label: this.lang.contactsParameters_lastname,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'function',
-            unit: 'mainInfo',
-            label: this.lang.contactsParameters_function,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'department',
-            unit: 'mainInfo',
-            label: this.lang.contactsParameters_department,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'email',
-            unit: 'mainInfo',
-            label: this.lang.email,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: true,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'phone',
-            unit: 'mainInfo',
-            label: this.lang.phoneNumber,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: true,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressNumber',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressNumber,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressStreet',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressStreet,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressAdditional1',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressAdditional1,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressAdditional2',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressAdditional2,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressPostcode',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressPostcode,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressTown',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressTown,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        },
-        {
-            id: 'addressCountry',
-            unit: 'address',
-            label: this.lang.contactsParameters_addressCountry,
-            type: 'string',
-            control: new FormControl(),
-            required: false,
-            display: false,
-            filling: false,
-            values: []
-        }
-    ];
-
-    addressBANInfo: string = '';
-    addressBANMode: boolean = true;
-    addressBANControl = new FormControl();
-    addressBANLoading: boolean = false;
-    addressBANResult: any[] = [];
-    addressBANFilteredResult: Observable<string[]>;
-    addressBANCurrentDepartment: string = '75';
-    departmentList: any[] = [];
-
-    fillingParameters: any = null;
-    fillingRate: any = {
-        class: 'warn',
-        value : 0
-    }
-
-    companyFound: any = null;
-
     constructor(
         public http: HttpClient,
         private route: ActivatedRoute,
         private router: Router,
-        private notify: NotificationService,
         private headerService: HeaderService,
         public appService: AppService,
-        public dialog: MatDialog,
-        private formBuilder: FormBuilder) { }
+        public dialog: MatDialog) { }
 
     ngOnInit(): void {
 
         this.loading = true;
-        
-        this.initBanSearch();
 
         this.route.params.subscribe((params: any) => {
             if (typeof params['id'] == "undefined") {
@@ -268,23 +71,8 @@ export class ContactsPageAdministrationComponent implements OnInit {
 
                 this.headerService.setHeader(this.lang.contactCreation);
                 this.creationMode = true;
+                this.loading = false;
 
-                this.http.get("../../rest/contactsCustomFields").pipe(
-                    tap((data: any) => {
-                        this.initCustomElementForm(data);
-                    }),
-                    exhaustMap(() => this.http.get("../../rest/contactsParameters")),
-                    tap((data: any) => {
-                        this.fillingParameters = data.contactsFilling;
-                        this.initElemForm(data);
-                        this.initAutocompleteAddressBan();
-                    }),
-                    finalize(() => this.loading = false),
-                    catchError((err: any) => {
-                        this.notify.handleErrors(err);
-                        return of(false);
-                    })
-                ).subscribe();
             } else {
                 window['MainHeaderComponent'].setSnav(this.sidenavLeft);
                 window['MainHeaderComponent'].setSnavRight(this.sidenavRight);
@@ -293,436 +81,14 @@ export class ContactsPageAdministrationComponent implements OnInit {
 
                 this.creationMode = false;
 
-                this.contactForm.forEach(element => {
-                    element.display = false;
-                });
-
-                this.http.get("../../rest/contactsCustomFields").pipe(
-                    tap((data: any) => {
-                        this.initCustomElementForm(data);
-                    }),
-                    exhaustMap(() => this.http.get("../../rest/contactsParameters")),
-                    tap((data: any) => {
-                        this.fillingParameters = data.contactsFilling;
-                        this.initElemForm(data);
-                        this.initAutocompleteAddressBan();
-                    }),
-                    exhaustMap(() => this.http.get("../../rest/contacts/" + params['id'])),
-                    tap((data) => {
-                        this.contactId = params['id'];
-                        this.setContactData(data);
-                    }),
-                    filter((data: any) => data.customFields !== null),
-                    tap((data: any) => {
-                       this.setContactCustomData(data);
-                    }),
-                    finalize(() => this.loading = false),
-                    catchError((err: any) => {
-                        this.notify.handleErrors(err);
-                        return of(false);
-                    })
-                ).subscribe();
-            }
-        });
-    }
-
-    initElemForm(data: any) {
-        let valArr: ValidatorFn[] = [];
-
-        data.contactsParameters.forEach((element: any) => {
-            valArr = [];
-
-            if ((element.mandatory || element.filling) && this.creationMode) {
-                this.contactForm.filter(contact => contact.id === element.identifier)[0].display = true;
-            }
-
-            if (element.filling) {
-                this.contactForm.filter(contact => contact.id === element.identifier)[0].filling = true;
-            }
-
-            if (element.identifier === 'email') {
-                valArr.push(Validators.email);
-            } else if (element.identifier === 'phone') {
-                valArr.push(Validators.pattern(/\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d$/));
-            }
-
-            if (element.mandatory) {
-                this.contactForm.filter(contact => contact.id === element.identifier)[0].required = true;
-                valArr.push(Validators.required);
-            }
-            
-            if(this.contactForm.filter(contact => contact.id === element.identifier)[0] !== undefined) {
-                this.contactForm.filter(contact => contact.id === element.identifier)[0].control.setValidators(valArr);
-            }
-            
-        });
-    }
-
-    initCustomElementForm(data: any) {
-        let valArr: ValidatorFn[] = [];
-
-        let field: any = {};
-
-        data.customFields.forEach((element: any) => {
-            valArr = [];
-
-            field = {
-                id: `customField_${element.id}`,
-                unit: 'complement',
-                label: element.label,
-                type: element.type,
-                control: new FormControl({ value: '', disabled: false }),
-                required: false,
-                display: false,
-                values: element.values.map((val: any) => { return { id: val, label: val } })
-            };
-
-            if (element.type === 'integer') {
-                valArr.push(Validators.pattern(/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$/));
-                field.control.setValidators(valArr);
-            }
-            this.contactForm.push(field);
-        });
-    }
-
-    setContactData(data: any) {
-        let indexField = -1;
-        Object.keys(data).forEach(element => {
-            indexField = this.contactForm.map(field => field.id).indexOf(element);
-            if (!this.isEmptyValue(data[element]) && indexField > -1) {
-                this.contactForm[indexField].control.setValue(data[element]);
-                this.contactForm[indexField].display = true;
-            }
-        });
-        this.checkFilling();
-    }
-
-    setContactCustomData(data: any) {
-        let indexField = -1;
-        Object.keys(data.customFields).forEach(element => {
-            indexField = this.contactForm.map(field => field.id).indexOf('customField_' + element);
-            if (!this.isEmptyValue(data[element]) && indexField > -1) {
-                this.contactForm[indexField].control.setValue(data.customFields[element]);
-                this.contactForm[indexField].display = true;
-            }
-        });
-        this.checkFilling();
-    }
-
-    initBanSearch() {
-        this.http.get("../../rest/ban/availableDepartments").pipe(
-            tap((data: any) => {
-                if (data.default !== null && data.departments.indexOf(data.default.toString()) !== - 1) {
-                    this.addressBANCurrentDepartment = data.default;
-                }
-                this.departmentList = data.departments;
-            }),
-            catchError((err: any) => {
-                this.notify.handleErrors(err);
-                return of(false);
-            })
-        ).subscribe();
-    }
-
-    isValidForm() {
-        let state = true;
- 
-        this.contactForm.filter(contact => contact.display).forEach(element => {
-            if (element.control.status !== 'VALID') {
-                state = false;
-            }
-            element.control.markAsTouched()
-        });
-
-        return state;
-    }
-
-    onSubmit() {
-        this.checkFilling();
-        if (this.addressBANMode && this.emptyAddress()) {
-            this.notify.error('Choisissez une BAN');
-        } else if (this.isValidForm()) {
-            if (this.contactId !== null) {
-                this.updateContact();
-            } else {
-                this.createContact();
-            }
-        } else {
-            this.notify.error('Veuillez corriger les erreurs');
-        }
-
-    }
-
-    createContact() {
-        this.http.post("../../rest/contacts", this.formatContact()).pipe(
-            tap(() => {
-                this.router.navigate(["/administration/contacts/list"]);
-                this.notify.success(this.lang.contactAdded);
-            }),
-            //finalize(() => this.loading = false),
-            catchError((err: any) => {
-                this.notify.handleErrors(err);
-                return of(false);
-            })
-        ).subscribe();
-    }
-
-    updateContact() {
-        this.http.put(`../../rest/contacts/${this.contactId}`, this.formatContact()).pipe(
-            tap(() => {
-                this.router.navigate(["/administration/contacts/list"]);
-                this.notify.success(this.lang.contactUpdated);
-            }),
-            //finalize(() => this.loading = false),
-            catchError((err: any) => {
-                this.notify.handleErrors(err);
-                return of(false);
-            })
-        ).subscribe();
-    }
-
-    formatContact() {
-        let contact: any = {};
-        contact['customFields'] = {};
-        const regex = /customField_[.]*/g;
+                this.contactId = params['id'];
 
-        this.contactForm.filter(field => field.display).forEach(element => {
-            if (element.id.match(regex) !== null) {
-                contact['customFields'][element.id.split('_')[1]] = element.control.value;
-            } else {
-                contact[element.id] = element.control.value;
+                this.loading = false;
             }
         });
-        return contact;
-    }
-
-    isEmptyUnit(id: string) {
-        if (this.contactForm.filter(field => field.display && field.unit === id).length === 0) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    initForm() {
-        this.contactForm.forEach(element => {
-            element.control = new FormControl({ value: '', disabled: false });
-        });
-    }
-
-    toogleAllFieldsUnit(idUnit: string) {
-        this.contactForm.filter(field => field.unit === idUnit).forEach((element: any) => {
-            element.display = true;
-        });
-    }
-
-    noField(id: string) {
-        if (this.contactForm.filter(field => !field.display && field.unit === id).length === 0) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    isEmptyValue(value: string) {
-
-        if (value === null) {
-            return true;
-
-        } else if (Array.isArray(value)) {
-            if (value.length > 0) {
-                return false;
-            } else {
-                return true;
-            }
-        } else if (String(value) !== '') {
-            return false;
-        } else {
-            return true;
-        }
     }
 
-    checkCompany(field: any) {
-        if (field.id === 'company' && (this.companyFound === null || this.companyFound.company !== field.control.value)) {
-
-            this.http.get(`../../rest/autocomplete/contacts/company?search=${field.control.value}`).pipe(
-                tap(() => this.companyFound = null),
-                filter((data: any) => data.length > 0),
-                tap((data) => {
-                    this.companyFound = data[0];
-                }),
-                //finalize(() => this.loading = false),
-                catchError((err: any) => {
-                    this.notify.handleErrors(err);
-                    return of(false);
-                })
-            ).subscribe();
-        }
-    }
-
-    setAddress(contact: any, disableBan: boolean = true) {
-        let indexField = -1;
-        Object.keys(contact).forEach(element => {
-            indexField = this.contactForm.map(field => field.id).indexOf(element);
-            if (!this.isEmptyValue(contact[element]) && indexField > -1 && ['company', 'addressNumber', 'addressStreet', 'addressAdditional2', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(element) > -1) {
-                this.contactForm[indexField].control.setValue(contact[element]);
-                this.contactForm[indexField].display = true;
-            }
-        });
-        this.checkFilling();
-
-        this.addressBANMode = disableBan ? false : true;
-    }
-
-    canDelete(field: any) {
-        if (field.id === "company") {
-            const lastname = this.contactForm.filter(contact => contact.id === 'lastname')[0];
-            if (lastname.display && !this.isEmptyValue(lastname.control.value)) {
-                let valArr: ValidatorFn[] = [];
-                field.control.setValidators(valArr);
-                field.required = false;
-                return true;
-            } else {
-                let valArr: ValidatorFn[] = [];
-                valArr.push(Validators.required);
-                field.control.setValidators(valArr);
-                field.required = true;
-                return false;
-            }
-        } else if (field.id === "lastname") {
-            const company = this.contactForm.filter(contact => contact.id === 'company')[0];
-            if (company.display && !this.isEmptyValue(company.control.value)) {
-                let valArr: ValidatorFn[] = [];
-                field.control.setValidators(valArr);
-                field.required = false;
-                return true;
-            } else {
-                let valArr: ValidatorFn[] = [];
-                valArr.push(Validators.required);
-                field.control.setValidators(valArr);
-                field.required = true;
-                return false;
-            }
-        } else if (field.required) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    removeField(field: any) {
-        field.display = !field.display;
-        field.control.reset();
-        this.checkFilling();
-    }
-
-    initAutocompleteAddressBan() {
-        this.addressBANInfo = this.lang.autocompleteInfo;
-        this.addressBANResult = [];
-        this.addressBANControl.valueChanges
-            .pipe(
-                debounceTime(300),
-                filter(value => value.length > 2),
-                distinctUntilChanged(),
-                tap(() => this.addressBANLoading = true),
-                switchMap((data: any) => this.http.get('../../rest/autocomplete/banAddresses', { params: { "address": data, 'department': this.addressBANCurrentDepartment } })),
-                tap((data: any) => {
-                    if (data.length === 0) {
-                        this.addressBANInfo = this.lang.noAvailableValue;
-                    } else {
-                        this.addressBANInfo = '';
-                    }
-                    this.addressBANResult = data;
-                    this.addressBANFilteredResult = of(this.addressBANResult);
-                    this.addressBANLoading = false;
-                })
-            ).subscribe();
-    }
-
-    resetAutocompleteAddressBan() {
-        this.addressBANResult = [];
-        this.addressBANInfo = this.lang.autocompleteInfo;
-    }
-
-    selectAddressBan(ev: any) {
-        let contact = {
-            addressNumber: ev.option.value.number,
-            addressStreet: ev.option.value.afnorName,
-            addressPostcode: ev.option.value.postalCode,
-            addressTown: ev.option.value.city,
-            addressCountry: 'FRANCE'
-        };
-        this.setAddress(contact, false);
-        this.addressBANControl.setValue('');
-    }
-
-    getValue(identifier: string) {
-        return this.contactForm.filter(contact => contact.id === identifier)[0].control.value;
-    }
-
-    emptyAddress() {
-        if (this.contactForm.filter(contact => this.isEmptyValue(contact.control.value) && ['addressNumber', 'addressStreet', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(contact.id) > -1).length > 0) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    goTo() {
-        const contact = {
-            addressNumber: this.contactForm.filter(contact => contact.id === 'addressNumber')[0].control.value,
-            addressStreet: this.contactForm.filter(contact => contact.id === 'addressStreet')[0].control.value,
-            addressPostcode: this.contactForm.filter(contact => contact.id === 'addressPostcode')[0].control.value,
-            addressTown: this.contactForm.filter(contact => contact.id === 'addressTown')[0].control.value,
-            addressCountry: this.contactForm.filter(contact => contact.id === 'addressCountry')[0].control.value
-        };
-        window.open(`https://www.google.com/maps/search/${contact.addressNumber}+${contact.addressStreet},+${contact.addressPostcode}+${contact.addressTown},+${contact.addressCountry}`, '_blank')
-    }
-
-    switchAddressMode() {
-        let valArr: ValidatorFn[] = [];
-        if (this.addressBANMode) {
-            
-            valArr.push(Validators.required);
-
-            this.contactForm.filter(contact => ['addressNumber', 'addressStreet', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(contact.id) > -1).forEach((element: any) => {
-                if (element.mandatory) {
-                    element.control.setValidators(valArr);
-                }
-            });
-            this.addressBANMode = !this.addressBANMode;
-        } else {
-            this.contactForm.filter(contact => ['addressNumber', 'addressStreet', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(contact.id) > -1).forEach((element: any) => {
-                if (element.mandatory) {
-                    element.control.setValidators(valArr);
-                }
-            });
-            this.addressBANMode = !this.addressBANMode;
-        }
-    }
-
-    getErrorMsg(error: any) {
-        if (error.required !== undefined) {
-            return this.lang.requiredField;
-        } else if (error.pattern !== undefined || error.email !== undefined) {
-            return this.lang.badFormat;
-        } else {
-            return 'unknow validator';
-        }
-    }
-
-    checkFilling() {
-        const countFilling = this.contactForm.filter(contact => contact.filling).length;
-        const countValNotEmpty = this.contactForm.filter(contact => !this.isEmptyValue(contact.control.value) && contact.filling).length;
-
-        this.fillingRate.value = Math.round((countValNotEmpty * 100) / countFilling);
-
-        if (this.fillingRate.value <= this.fillingParameters.first_threshold) {
-            this.fillingRate.class = 'warn';
-        } else if (this.fillingRate.value <= this.fillingParameters.second_threshold) {
-            this.fillingRate.class = 'primary';
-        } else {
-            this.fillingRate.class = 'accent';
-        }        
+    goToList() {
+        this.router.navigate(["/administration/contacts/list"]);
     }
 }
diff --git a/src/frontend/app/administration/contact/page/form/contacts-form.component.html b/src/frontend/app/administration/contact/page/form/contacts-form.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..399ba5e74c94509a5facd54e552acc9df224924c
--- /dev/null
+++ b/src/frontend/app/administration/contact/page/form/contacts-form.component.html
@@ -0,0 +1,226 @@
+<div class="loading" *ngIf="loading; else elseTemplate">
+    <mat-spinner style="margin:auto;"></mat-spinner>
+</div>
+<ng-template #elseTemplate>
+    <mat-menu #menu="matMenu">
+        <button mat-menu-item [matMenuTriggerFor]="mainInfo"
+            [disabled]="noField('mainInfo')">{{lang.denomination}}</button>
+        <button mat-menu-item [matMenuTriggerFor]="address" [disabled]="noField('address')">{{lang.address}}</button>
+        <button mat-menu-item [matMenuTriggerFor]="complement"
+            [disabled]="noField('complement')">{{lang.additionals}}</button>
+    </mat-menu>
+
+    <mat-menu #mainInfo="matMenu">
+        <button mat-menu-item (click)="toogleAllFieldsUnit('mainInfo')"
+            style="text-align: center;">{{lang.addAll}}</button>
+        <mat-divider></mat-divider>
+        <ng-container *ngFor="let field of contactForm">
+            <button mat-menu-item *ngIf="!field.display && field.unit === 'mainInfo'"
+                (click)="field.display=!field.display">
+                <mat-icon *ngIf="field.filling" style="height: auto;padding-right: 10px;"
+                    [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
+                <span>{{field.label}}</span>
+            </button>
+        </ng-container>
+    </mat-menu>
+
+    <mat-menu #address="matMenu">
+        <button mat-menu-item (click)="toogleAllFieldsUnit('address')"
+            style="text-align: center;">{{lang.addAll}}</button>
+        <mat-divider></mat-divider>
+        <ng-container *ngFor="let field of contactForm">
+            <button mat-menu-item *ngIf="!field.display && field.unit === 'address'"
+                (click)="field.display=!field.display">
+                <mat-icon *ngIf="field.filling" style="height: auto;padding-right: 10px;"
+                    [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
+                <span>{{field.label}}</span>
+            </button>
+        </ng-container>
+    </mat-menu>
+    <mat-menu #complement="matMenu">
+        <button mat-menu-item (click)="toogleAllFieldsUnit('complement')"
+            style="text-align: center;">{{lang.addAll}}</button>
+        <mat-divider></mat-divider>
+        <ng-container *ngFor="let field of contactForm">
+            <button mat-menu-item *ngIf="!field.display && field.unit === 'complement'"
+                (click)="field.display=!field.display">
+                <mat-icon *ngIf="field.filling" style="height: auto;padding-right: 10px;"
+                    [title]="lang.targetFillingField" class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
+                <span>{{field.label}}</span>
+            </button>
+        </ng-container>
+    </mat-menu>
+    <div style="padding: 10px;">
+        <div class="rate_{{fillingRate.class}}">{{lang.contactFilledTo}} <b>{{fillingRate.value}} %</b></div>
+        <mat-progress-bar mode="determinate" class="fillingBar" [color]="fillingRate.class" [value]="fillingRate.value">
+        </mat-progress-bar>
+
+    </div>
+    <div [class.multipleUnits]="!isEmptyUnit('address') || !isEmptyUnit('complement')">
+        <ng-container *ngFor="let unit of contactUnit">
+            <div *ngIf="!isEmptyUnit(unit.id)">
+                <mat-list>
+                    <h3 mat-subheader class="unitTitle"><span style="flex:1">{{unit.label}}</span><a
+                            *ngIf="unit.id === 'address'" (click)="addressBANMode=!addressBANMode"
+                            style="cursor: pointer;">{{addressBANMode ? lang.switchManualAddress : lang.searchAddressDb}}</a>
+                    </h3>
+                    <ng-container *ngFor="let field of contactForm;let i=index">
+                        <mat-list-item class="contact-item"
+                            *ngIf="(field.unit === unit.id && unit.id !== 'address') || (field.unit === unit.id && unit.id === 'address' && !addressBANMode)">
+                            <p mat-line class="contact-content" *ngIf="field.display">
+                                <ng-container *ngIf="field.type === 'string'">
+                                    <mat-form-field>
+                                        <input matInput [formControl]="field.control" [placeholder]="field.label"
+                                            (blur)="checkCompany(field);checkFilling();" [required]="field.required">
+                                        <mat-hint *ngIf="companyFound !== null && field.id === 'company'" align="end">
+                                            {{lang.contactsParameters_company}} <b>{{companyFound.company}}</b>
+                                            {{lang.found}}
+                                            !
+                                            cliquez <a (click)="setAddress(companyFound)"
+                                                style="cursor: pointer;font-weight:bold;">{{lang.here}}</a>
+                                            {{lang.toCopyAddress}}</mat-hint>
+                                        <mat-error *ngIf="field.control.status!=='VALID'  && field.control.touched">
+                                            {{getErrorMsg(field.control.errors)}}</mat-error>
+                                        <mat-icon style="height: auto;" matSuffix [title]="lang.targetFillingField"
+                                            class="fas fa-circle rate_{{fillingRate.class}}"></mat-icon>
+                                    </mat-form-field>
+                                </ng-container>
+                                <ng-container *ngIf="field.type === 'integer'">
+                                    <mat-form-field>
+                                        <input type="text" matInput [formControl]="field.control"
+                                            [placeholder]="field.label" min="0" step="0.1" [required]="field.required">
+                                        <mat-error *ngIf="field.control.status!=='VALID' && field.control.touched">
+                                            {{getErrorMsg(field.control.errors)}}</mat-error>
+                                    </mat-form-field>
+                                </ng-container>
+                                <ng-container *ngIf="field.type === 'select'">
+                                    <plugin-select-search [label]="field.label" [showLabel]="true"
+                                        [formControlSelect]="field.control" [placeholderLabel]="field.label"
+                                        [datas]="field.values" [class]="''">
+                                    </plugin-select-search>
+                                </ng-container>
+                                <ng-container *ngIf="field.type === 'date'">
+                                    <mat-form-field (click)="picker.open()" style="cursor:pointer;">
+                                        <mat-label>{{field.label}}
+                                        </mat-label>
+                                        <input [formControl]="field.control" matInput [matDatepicker]="picker"
+                                            [placeholder]="field.label" readonly style="cursor:pointer;">
+                                        <mat-datepicker-toggle matSuffix [for]="picker" *ngIf="!field.control.value">
+                                        </mat-datepicker-toggle>
+                                        <mat-datepicker [touchUi]="appService.getViewMode()" #picker>
+                                        </mat-datepicker>
+                                        <button mat-button color="warn" matSuffix mat-icon-button
+                                            *ngIf="field.control.value && !field.control.disabled"
+                                            (click)="$event.stopPropagation();field.control.reset();"
+                                            [title]="lang.eraseValue">
+                                            <mat-icon color="warn" class="fa fa-calendar-times">
+                                            </mat-icon>
+                                        </button>
+                                    </mat-form-field>
+                                </ng-container>
+                                <ng-container *ngIf="field.type === 'radio'">
+                                    <mat-radio-group class="radio-form" color="primary" [formControl]="field.control">
+                                        <mat-radio-button *ngFor="let value of field.values" [value]="value.id">
+                                            {{value.label}}
+                                        </mat-radio-button>
+                                    </mat-radio-group>
+                                </ng-container>
+                                <ng-container *ngIf="field.type === 'checkbox'">
+                                    <mat-selection-list #shoes class="checkbox-form" [formControl]="field.control">
+                                        <mat-list-option *ngFor="let value of field.values" [value]="value.id"
+                                            color="primary" checkboxPosition="before">
+                                            {{value.label}}
+                                        </mat-list-option>
+                                    </mat-selection-list>
+                                </ng-container>
+                            </p>
+                            <button *ngIf="field.display" [disabled]="!canDelete(field)" mat-icon-button matSuffix
+                                color="warn" (click)="removeField(field)">
+                                <mat-icon class="fa fa-trash"></mat-icon>
+                            </button>
+                        </mat-list-item>
+                        <ng-container
+                            *ngIf="unit.id === 'address' && addressBANMode && ['addressAdditional1', 'addressAdditional2'].indexOf(field.id) > -1">
+                            <mat-list-item class="contact-item">
+                                <p mat-line class="contact-content" *ngIf="field.display">
+                                    <mat-form-field>
+                                        <input matInput [formControl]="field.control" [placeholder]="field.label"
+                                            [required]="field.required">
+                                        <mat-error *ngIf="field.control.hasError('required')">
+                                            {{lang.requiredField}}</mat-error>
+                                    </mat-form-field>
+                                </p>
+                                <button *ngIf="field.display" [disabled]="!canDelete(field)" mat-icon-button matSuffix
+                                    color="warn" (click)="removeField(field)">
+                                    <mat-icon class="fa fa-trash"></mat-icon>
+                                </button>
+                            </mat-list-item>
+                        </ng-container>
+                        <ng-container *ngIf="unit.id === 'address' && addressBANMode && i === 0">
+                            <mat-list-item>
+                                <p mat-line class="contact-content">
+                                    <mat-form-field appearance='outline' class="smallInput">
+                                        <button mat-button matSuffix [matMenuTriggerFor]="menuDep"
+                                            (click)="$event.stopPropagation();" [title]="lang.targetDepartment">
+                                            {{addressBANCurrentDepartment}}&nbsp;<i class="fa fa-chevron-down"></i>
+                                        </button>
+                                        <mat-menu #menuDep="matMenu">
+                                            <button mat-menu-item *ngFor="let dep of departmentList"
+                                                (click)="addressBANCurrentDepartment = dep">{{dep}}</button>
+                                        </mat-menu>
+                                        <mat-icon color="primary" class="fa fa-search" matPrefix
+                                            style="font-size: 15px;"></mat-icon>
+                                        <input type="text" #autoCompleteInput [placeholder]="lang.searchAddressBan"
+                                            matInput [formControl]="addressBANControl" [matAutocomplete]="auto"
+                                            (click)="$event.stopPropagation()" (focus)="resetAutocompleteAddressBan()"
+                                            maxlength="128">
+                                        <mat-autocomplete #auto="matAutocomplete"
+                                            (optionSelected)="selectAddressBan($event)">
+                                            <ng-container *ngIf="addressBANResult.length > 0 && !addressBANLoading">
+                                                <mat-option
+                                                    *ngFor="let addressBANResult of addressBANFilteredResult | async"
+                                                    [value]="addressBANResult">
+                                                    {{addressBANResult.address}}
+                                                </mat-option>
+                                            </ng-container>
+                                            <mat-option class="autoCompleteInfoResult smallInputInfo"
+                                                *ngIf="addressBANResult.length === 0 && !addressBANLoading" disabled
+                                                [innerHTML]="addressBANInfo">
+                                            </mat-option>
+                                            <mat-option *ngIf="addressBANLoading" disabled>
+                                                <mat-spinner diameter="20"></mat-spinner>
+                                            </mat-option>
+                                        </mat-autocomplete>
+                                    </mat-form-field>
+                                    <mat-card style="margin:10px;" *ngIf="!emptyAddress()">
+                                        <mat-list-item class="contact-address" (click)="goTo(contact)"
+                                            [title]="lang.address">
+                                            <mat-icon mat-list-icon color="primary"
+                                                class="contact-group fas fa-map-marker-alt"></mat-icon>
+                                            <p mat-line class="contact-content">
+                                                {{getValue('addressNumber')}}
+                                                {{getValue('addressStreet')}}
+                                            </p>
+                                            <p mat-line class="contact-content">
+                                                {{getValue('addressPostcode')}}
+                                                {{getValue('addressTown')}}
+                                            </p>
+                                            <p mat-line class="contact-content">
+                                                {{getValue('addressCountry')}} </p>
+                                        </mat-list-item>
+                                    </mat-card>
+                                </p>
+                            </mat-list-item>
+                        </ng-container>
+                    </ng-container>
+                </mat-list>
+            </div>
+        </ng-container>
+    </div>
+    <div style="text-align:center;">
+        <button mat-raised-button color="default" type="button"
+            [matMenuTriggerFor]="menu">{{lang.moreInfos}}...</button>
+
+        <button mat-raised-button color="primary" type="button" (click)="onSubmit()">{{lang.validate}}</button>
+    </div>
+</ng-template>
\ No newline at end of file
diff --git a/src/frontend/app/administration/contact/page/form/contacts-form.component.scss b/src/frontend/app/administration/contact/page/form/contacts-form.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..d6412bdd07d8ba60c2a00c6d68aca002d89ee639
--- /dev/null
+++ b/src/frontend/app/administration/contact/page/form/contacts-form.component.scss
@@ -0,0 +1,117 @@
+@import '../../../../../css/vars.scss';
+
+.contact-item {
+    height: auto !important;
+}
+
+.multipleUnits div:nth-child(1) {
+    display: inline-grid !important;
+    width: 50%;
+}
+
+.multipleUnits div:nth-child(2) {
+    display: inline-grid !important;
+    width: 50%;
+}
+
+.unitTitle {
+    display: flex;
+    color: $primary;
+}
+
+.contact-address {
+    cursor: pointer;
+    color: #337ab7;
+
+    &:hover {
+        .contact-content {
+            text-decoration: underline;
+        }
+    }
+}
+
+.smallInput {
+    font-size: 11px;
+    padding-left: 20px;
+    padding-right: 20px;
+    .mat-button {
+        width: 30px;
+        height: 25px;
+        color: $primary;
+
+        ::ng-deep.mat-button-wrapper {
+            display: flex;
+            line-height: initial;
+            align-items: center;
+        }
+    }
+    ::ng-deep.mat-form-field-infix {
+        padding : 0px;
+        padding-bottom: 5px;
+    }
+}
+.radio-form {
+    display: flex;
+
+    .mat-radio-button {
+        flex: 1;
+    }
+}
+
+.checkbox-form {
+    overflow: auto;
+    max-height: 200px;
+}
+
+.loading {
+    display: flex;
+    height: 100%;
+}
+
+.fillingBar {
+    ::ng-deep .mat-progress-bar-buffer {
+        background: #E4E8EB;
+    }
+}
+
+.rate_primary {
+    font-size: 10px;
+    text-align: right;
+    color: orange;
+}
+
+.rate_warn {
+    font-size: 10px;
+    text-align: right;
+    color: red;
+}
+
+.rate_accent {
+    font-size: 10px;
+    text-align: right;
+    color: green;
+}
+
+.fillingBar.mat-warn {
+    ::ng-deep.mat-progress-bar-fill::after {
+        background-color: red;
+    }
+}
+
+.fillingBar.mat-primary {
+    ::ng-deep.mat-progress-bar-fill::after {
+        background-color: orange;
+    }
+}
+
+.fillingBar.mat-accent {
+    ::ng-deep.mat-progress-bar-fill::after {
+        background-color: green;
+    }
+}
+
+.mat-error {
+    font-size: 10px;
+    text-align: right;
+    font-weight: bold;
+}
\ No newline at end of file
diff --git a/src/frontend/app/administration/contact/page/form/contacts-form.component.ts b/src/frontend/app/administration/contact/page/form/contacts-form.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2250f51b373a7bc4ab81d1f1412bdf08c9a7efdc
--- /dev/null
+++ b/src/frontend/app/administration/contact/page/form/contacts-form.component.ts
@@ -0,0 +1,691 @@
+import { Component, OnInit, ViewChild, EventEmitter, Input, Output } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { LANG } from '../../../../translate.component';
+import { NotificationService } from '../../../../notification.service';
+import { HeaderService } from '../../../../../service/header.service';
+import { MatSidenav } from '@angular/material/sidenav';
+import { AppService } from '../../../../../service/app.service';
+import { Observable, merge, Subject, of as observableOf, of } from 'rxjs';
+import { MatPaginator, MatSort, MatDialog } from '@angular/material';
+import { startWith, switchMap, map, catchError, filter, exhaustMap, tap, debounceTime, distinctUntilChanged, finalize, count } from 'rxjs/operators';
+import { FormControl, Validators, ValidatorFn, FormGroup, FormBuilder } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+@Component({
+    selector: 'app-contact-form',
+    templateUrl: "contacts-form.component.html",
+    styleUrls: ['contacts-form.component.scss'],
+    providers: [NotificationService, AppService]
+})
+export class ContactsFormComponent implements OnInit {
+
+    @ViewChild('snav', { static: true }) public sidenavLeft: MatSidenav;
+    @ViewChild('snav2', { static: true }) public sidenavRight: MatSidenav;
+
+    lang: any = LANG;
+    loading: boolean = false;
+
+    @Input() creationMode: boolean = true;
+    @Input() contactId: number = null;
+
+    @Output() onSubmitEvent = new EventEmitter<number>();
+
+    contactUnit = [
+        {
+            id: 'mainInfo',
+            label: this.lang.denomination
+        },
+        {
+            id: 'address',
+            label: this.lang.address
+        },
+        {
+            id: 'complement',
+            label: this.lang.additionals
+        }
+    ];
+
+    contactForm: any[] = [
+        {
+            id: 'company',
+            unit: 'mainInfo',
+            label: this.lang.contactsParameters_company,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: true,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'firstname',
+            unit: 'mainInfo',
+            label: this.lang.contactsParameters_firstname,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'lastname',
+            unit: 'mainInfo',
+            label: this.lang.contactsParameters_lastname,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'function',
+            unit: 'mainInfo',
+            label: this.lang.contactsParameters_function,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'department',
+            unit: 'mainInfo',
+            label: this.lang.contactsParameters_department,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'email',
+            unit: 'mainInfo',
+            label: this.lang.email,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: true,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'phone',
+            unit: 'mainInfo',
+            label: this.lang.phoneNumber,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: true,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressNumber',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressNumber,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressStreet',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressStreet,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressAdditional1',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressAdditional1,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressAdditional2',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressAdditional2,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressPostcode',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressPostcode,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressTown',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressTown,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        },
+        {
+            id: 'addressCountry',
+            unit: 'address',
+            label: this.lang.contactsParameters_addressCountry,
+            type: 'string',
+            control: new FormControl(),
+            required: false,
+            display: false,
+            filling: false,
+            values: []
+        }
+    ];
+
+    addressBANInfo: string = '';
+    addressBANMode: boolean = true;
+    addressBANControl = new FormControl();
+    addressBANLoading: boolean = false;
+    addressBANResult: any[] = [];
+    addressBANFilteredResult: Observable<string[]>;
+    addressBANCurrentDepartment: string = '75';
+    departmentList: any[] = [];
+
+    fillingParameters: any = null;
+    fillingRate: any = {
+        class: 'warn',
+        value: 0
+    }
+
+    companyFound: any = null;
+
+    constructor(
+        public http: HttpClient,
+        private route: ActivatedRoute,
+        private router: Router,
+        private notify: NotificationService,
+        private headerService: HeaderService,
+        public appService: AppService,
+        public dialog: MatDialog
+    ) { }
+
+    ngOnInit(): void {
+
+        this.loading = true;
+
+        this.initBanSearch();
+
+        if (this.contactId === null) {
+
+            this.creationMode = true;
+
+            this.http.get("../../rest/contactsCustomFields").pipe(
+                tap((data: any) => {
+                    this.initCustomElementForm(data);
+                }),
+                exhaustMap(() => this.http.get("../../rest/contactsParameters")),
+                tap((data: any) => {
+                    this.fillingParameters = data.contactsFilling;
+                    this.initElemForm(data);
+                    this.initAutocompleteAddressBan();
+                }),
+                finalize(() => this.loading = false),
+                catchError((err: any) => {
+                    this.notify.handleErrors(err);
+                    return of(false);
+                })
+            ).subscribe();
+        } else {
+            this.creationMode = false;
+
+            this.contactForm.forEach(element => {
+                element.display = false;
+            });
+
+            this.http.get("../../rest/contactsCustomFields").pipe(
+                tap((data: any) => {
+                    this.initCustomElementForm(data);
+                }),
+                exhaustMap(() => this.http.get("../../rest/contactsParameters")),
+                tap((data: any) => {
+                    this.fillingParameters = data.contactsFilling;
+                    this.initElemForm(data);
+                    this.initAutocompleteAddressBan();
+                }),
+                exhaustMap(() => this.http.get("../../rest/contacts/" + this.contactId)),
+                tap((data) => {
+                    this.setContactData(data);
+                }),
+                filter((data: any) => data.customFields !== null),
+                tap((data: any) => {
+                    this.setContactCustomData(data);
+                }),
+                finalize(() => this.loading = false),
+                catchError((err: any) => {
+                    this.notify.handleErrors(err);
+                    return of(false);
+                })
+            ).subscribe();
+        }
+    }
+
+    initElemForm(data: any) {
+        let valArr: ValidatorFn[] = [];
+
+        data.contactsParameters.forEach((element: any) => {
+            valArr = [];
+
+            if ((element.mandatory || element.filling) && this.creationMode) {
+                this.contactForm.filter(contact => contact.id === element.identifier)[0].display = true;
+            }
+
+            if (element.filling) {
+                this.contactForm.filter(contact => contact.id === element.identifier)[0].filling = true;
+            }
+
+            if (element.identifier === 'email') {
+                valArr.push(Validators.email);
+            } else if (element.identifier === 'phone') {
+                valArr.push(Validators.pattern(/\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d$/));
+            }
+
+            if (element.mandatory) {
+                this.contactForm.filter(contact => contact.id === element.identifier)[0].required = true;
+                valArr.push(Validators.required);
+            }
+
+            if (this.contactForm.filter(contact => contact.id === element.identifier)[0] !== undefined) {
+                this.contactForm.filter(contact => contact.id === element.identifier)[0].control.setValidators(valArr);
+            }
+
+        });
+    }
+
+    initCustomElementForm(data: any) {
+        let valArr: ValidatorFn[] = [];
+
+        let field: any = {};
+
+        data.customFields.forEach((element: any) => {
+            valArr = [];
+
+            field = {
+                id: `customField_${element.id}`,
+                unit: 'complement',
+                label: element.label,
+                type: element.type,
+                control: new FormControl({ value: '', disabled: false }),
+                required: false,
+                display: false,
+                values: element.values.map((val: any) => { return { id: val, label: val } })
+            };
+
+            if (element.type === 'integer') {
+                valArr.push(Validators.pattern(/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$/));
+                field.control.setValidators(valArr);
+            }
+            this.contactForm.push(field);
+        });
+    }
+
+    setContactData(data: any) {
+        let indexField = -1;
+        Object.keys(data).forEach(element => {
+            indexField = this.contactForm.map(field => field.id).indexOf(element);
+            if (!this.isEmptyValue(data[element]) && indexField > -1) {
+                this.contactForm[indexField].control.setValue(data[element]);
+                this.contactForm[indexField].display = true;
+            }
+        });
+        this.checkFilling();
+    }
+
+    setContactCustomData(data: any) {
+        let indexField = -1;
+        Object.keys(data.customFields).forEach(element => {
+            indexField = this.contactForm.map(field => field.id).indexOf('customField_' + element);
+            if (!this.isEmptyValue(data[element]) && indexField > -1) {
+                this.contactForm[indexField].control.setValue(data.customFields[element]);
+                this.contactForm[indexField].display = true;
+            }
+        });
+        this.checkFilling();
+    }
+
+    initBanSearch() {
+        this.http.get("../../rest/ban/availableDepartments").pipe(
+            tap((data: any) => {
+                if (data.default !== null && data.departments.indexOf(data.default.toString()) !== - 1) {
+                    this.addressBANCurrentDepartment = data.default;
+                }
+                this.departmentList = data.departments;
+            }),
+            catchError((err: any) => {
+                this.notify.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
+    isValidForm() {
+        let state = true;
+
+        this.contactForm.filter(contact => contact.display).forEach(element => {
+            if (element.control.status !== 'VALID') {
+                state = false;
+            }
+            element.control.markAsTouched()
+        });
+
+        return state;
+    }
+
+    onSubmit() {
+        this.checkFilling();
+        if (this.addressBANMode && this.emptyAddress()) {
+            this.notify.error('Choisissez une BAN');
+        } else if (this.isValidForm()) {
+            if (this.contactId !== null) {
+                this.updateContact();
+            } else {
+                this.createContact();
+            }
+        } else {
+            this.notify.error('Veuillez corriger les erreurs');
+        }
+
+    }
+
+    createContact() {
+        this.http.post("../../rest/contacts", this.formatContact()).pipe(
+            tap((data:any) => {
+                this.onSubmitEvent.emit(data.id);
+                this.notify.success(this.lang.contactAdded);
+            }),
+            //finalize(() => this.loading = false),
+            catchError((err: any) => {
+                this.notify.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
+    updateContact() {
+        this.http.put(`../../rest/contacts/${this.contactId}`, this.formatContact()).pipe(
+            tap(() => {
+                this.onSubmitEvent.emit(this.contactId);
+                this.notify.success(this.lang.contactUpdated);
+            }),
+            //finalize(() => this.loading = false),
+            catchError((err: any) => {
+                this.notify.handleErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
+    formatContact() {
+        let contact: any = {};
+        contact['customFields'] = {};
+        const regex = /customField_[.]*/g;
+
+        this.contactForm.filter(field => field.display).forEach(element => {
+            if (element.id.match(regex) !== null) {
+                contact['customFields'][element.id.split('_')[1]] = element.control.value;
+            } else {
+                contact[element.id] = element.control.value;
+            }
+        });
+        return contact;
+    }
+
+    isEmptyUnit(id: string) {
+        if (this.contactForm.filter(field => field.display && field.unit === id).length === 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    initForm() {
+        this.contactForm.forEach(element => {
+            element.control = new FormControl({ value: '', disabled: false });
+        });
+    }
+
+    toogleAllFieldsUnit(idUnit: string) {
+        this.contactForm.filter(field => field.unit === idUnit).forEach((element: any) => {
+            element.display = true;
+        });
+    }
+
+    noField(id: string) {
+        if (this.contactForm.filter(field => !field.display && field.unit === id).length === 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    isEmptyValue(value: string) {
+
+        if (value === null) {
+            return true;
+
+        } else if (Array.isArray(value)) {
+            if (value.length > 0) {
+                return false;
+            } else {
+                return true;
+            }
+        } else if (String(value) !== '') {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    checkCompany(field: any) {
+        if (field.id === 'company' && (this.companyFound === null || this.companyFound.company !== field.control.value)) {
+
+            this.http.get(`../../rest/autocomplete/contacts/company?search=${field.control.value}`).pipe(
+                tap(() => this.companyFound = null),
+                filter((data: any) => data.length > 0),
+                tap((data) => {
+                    this.companyFound = data[0];
+                }),
+                //finalize(() => this.loading = false),
+                catchError((err: any) => {
+                    this.notify.handleErrors(err);
+                    return of(false);
+                })
+            ).subscribe();
+        }
+    }
+
+    setAddress(contact: any, disableBan: boolean = true) {
+        let indexField = -1;
+        Object.keys(contact).forEach(element => {
+            indexField = this.contactForm.map(field => field.id).indexOf(element);
+            if (!this.isEmptyValue(contact[element]) && indexField > -1 && ['company', 'addressNumber', 'addressStreet', 'addressAdditional2', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(element) > -1) {
+                this.contactForm[indexField].control.setValue(contact[element]);
+                this.contactForm[indexField].display = true;
+            }
+        });
+        this.checkFilling();
+
+        this.addressBANMode = disableBan ? false : true;
+    }
+
+    canDelete(field: any) {
+        if (field.id === "company") {
+            const lastname = this.contactForm.filter(contact => contact.id === 'lastname')[0];
+            if (lastname.display && !this.isEmptyValue(lastname.control.value)) {
+                let valArr: ValidatorFn[] = [];
+                field.control.setValidators(valArr);
+                field.required = false;
+                return true;
+            } else {
+                let valArr: ValidatorFn[] = [];
+                valArr.push(Validators.required);
+                field.control.setValidators(valArr);
+                field.required = true;
+                return false;
+            }
+        } else if (field.id === "lastname") {
+            const company = this.contactForm.filter(contact => contact.id === 'company')[0];
+            if (company.display && !this.isEmptyValue(company.control.value)) {
+                let valArr: ValidatorFn[] = [];
+                field.control.setValidators(valArr);
+                field.required = false;
+                return true;
+            } else {
+                let valArr: ValidatorFn[] = [];
+                valArr.push(Validators.required);
+                field.control.setValidators(valArr);
+                field.required = true;
+                return false;
+            }
+        } else if (field.required) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    removeField(field: any) {
+        field.display = !field.display;
+        field.control.reset();
+        this.checkFilling();
+    }
+
+    initAutocompleteAddressBan() {
+        this.addressBANInfo = this.lang.autocompleteInfo;
+        this.addressBANResult = [];
+        this.addressBANControl.valueChanges
+            .pipe(
+                debounceTime(300),
+                filter(value => value.length > 2),
+                distinctUntilChanged(),
+                tap(() => this.addressBANLoading = true),
+                switchMap((data: any) => this.http.get('../../rest/autocomplete/banAddresses', { params: { "address": data, 'department': this.addressBANCurrentDepartment } })),
+                tap((data: any) => {
+                    if (data.length === 0) {
+                        this.addressBANInfo = this.lang.noAvailableValue;
+                    } else {
+                        this.addressBANInfo = '';
+                    }
+                    this.addressBANResult = data;
+                    this.addressBANFilteredResult = of(this.addressBANResult);
+                    this.addressBANLoading = false;
+                })
+            ).subscribe();
+    }
+
+    resetAutocompleteAddressBan() {
+        this.addressBANResult = [];
+        this.addressBANInfo = this.lang.autocompleteInfo;
+    }
+
+    selectAddressBan(ev: any) {
+        let contact = {
+            addressNumber: ev.option.value.number,
+            addressStreet: ev.option.value.afnorName,
+            addressPostcode: ev.option.value.postalCode,
+            addressTown: ev.option.value.city,
+            addressCountry: 'FRANCE'
+        };
+        this.setAddress(contact, false);
+        this.addressBANControl.setValue('');
+    }
+
+    getValue(identifier: string) {
+        return this.contactForm.filter(contact => contact.id === identifier)[0].control.value;
+    }
+
+    emptyAddress() {
+        if (this.contactForm.filter(contact => this.isEmptyValue(contact.control.value) && ['addressNumber', 'addressStreet', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(contact.id) > -1).length > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    goTo() {
+        const contact = {
+            addressNumber: this.contactForm.filter(contact => contact.id === 'addressNumber')[0].control.value,
+            addressStreet: this.contactForm.filter(contact => contact.id === 'addressStreet')[0].control.value,
+            addressPostcode: this.contactForm.filter(contact => contact.id === 'addressPostcode')[0].control.value,
+            addressTown: this.contactForm.filter(contact => contact.id === 'addressTown')[0].control.value,
+            addressCountry: this.contactForm.filter(contact => contact.id === 'addressCountry')[0].control.value
+        };
+        window.open(`https://www.google.com/maps/search/${contact.addressNumber}+${contact.addressStreet},+${contact.addressPostcode}+${contact.addressTown},+${contact.addressCountry}`, '_blank')
+    }
+
+    switchAddressMode() {
+        let valArr: ValidatorFn[] = [];
+        if (this.addressBANMode) {
+
+            valArr.push(Validators.required);
+
+            this.contactForm.filter(contact => ['addressNumber', 'addressStreet', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(contact.id) > -1).forEach((element: any) => {
+                if (element.mandatory) {
+                    element.control.setValidators(valArr);
+                }
+            });
+            this.addressBANMode = !this.addressBANMode;
+        } else {
+            this.contactForm.filter(contact => ['addressNumber', 'addressStreet', 'addressPostcode', 'addressTown', 'addressCountry'].indexOf(contact.id) > -1).forEach((element: any) => {
+                if (element.mandatory) {
+                    element.control.setValidators(valArr);
+                }
+            });
+            this.addressBANMode = !this.addressBANMode;
+        }
+    }
+
+    getErrorMsg(error: any) {
+        if (error.required !== undefined) {
+            return this.lang.requiredField;
+        } else if (error.pattern !== undefined || error.email !== undefined) {
+            return this.lang.badFormat;
+        } else {
+            return 'unknow validator';
+        }
+    }
+
+    checkFilling() {
+        const countFilling = this.contactForm.filter(contact => contact.filling).length;
+        const countValNotEmpty = this.contactForm.filter(contact => !this.isEmptyValue(contact.control.value) && contact.filling).length;
+
+        this.fillingRate.value = Math.round((countValNotEmpty * 100) / countFilling);
+
+        if (this.fillingRate.value <= this.fillingParameters.first_threshold) {
+            this.fillingRate.class = 'warn';
+        } else if (this.fillingRate.value <= this.fillingParameters.second_threshold) {
+            this.fillingRate.class = 'primary';
+        } else {
+            this.fillingRate.class = 'accent';
+        }
+    }
+}
diff --git a/src/frontend/app/app-common.module.ts b/src/frontend/app/app-common.module.ts
index 3fcb0be54a81f5b544a173dff8492e649f6eb471..4b61ada4829dbfff905c4e93122e14594c7e5ade 100755
--- a/src/frontend/app/app-common.module.ts
+++ b/src/frontend/app/app-common.module.ts
@@ -60,6 +60,7 @@ import { FolderInputComponent }                        from '../app/folder/index
 import { TagInputComponent }                        from '../app/tag/indexing/tag-input.component';
 import { DragDropDirective }                        from '../app/viewer/upload-file-dnd.directive';
 import { ContactAutocompleteComponent } from './contact/autocomplete/contact-autocomplete.component';
+import { ContactsFormComponent }    from './administration/contact/page/form/contacts-form.component';
 
 
 import { DiffusionsListComponent }             from './diffusions/diffusions-list.component';
@@ -120,7 +121,8 @@ export class MyHammerConfig extends HammerGestureConfig {
         DocumentViewerComponent,
         DragDropDirective,
         EcplOnlyofficeViewerComponent,
-        ContactAutocompleteComponent
+        ContactAutocompleteComponent,
+        ContactsFormComponent
     ],
     exports: [
         CommonModule,
@@ -161,7 +163,8 @@ export class MyHammerConfig extends HammerGestureConfig {
         DocumentViewerComponent,
         DragDropDirective,
         EcplOnlyofficeViewerComponent,
-        ContactAutocompleteComponent
+        ContactAutocompleteComponent,
+        ContactsFormComponent
     ],
     providers: [
         HeaderService,
diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts
index 39138fcc9318d97c4f82272f6cb4bf237ad46b04..73c6b1f41d7abadc42fd35b87914961b7f1af9cb 100755
--- a/src/frontend/app/app.module.ts
+++ b/src/frontend/app/app.module.ts
@@ -82,6 +82,7 @@ import { PrivilegeService } from '../service/privileges.service';
 import { ActionsService } from './actions/actions.service';
 import { ContactsListComponent } from './contact/list/contacts-list.component';
 import { ContactsListModalComponent } from './contact/list/modal/contacts-list-modal.component';
+import { ContactModalComponent } from './administration/contact/modal/contact-modal.component';
 
 
 @NgModule({
@@ -156,6 +157,7 @@ import { ContactsListModalComponent } from './contact/list/modal/contacts-list-m
         MailResumeComponent,
         ContactsListComponent,
         ContactsListModalComponent,
+        ContactModalComponent
     ],
     entryComponents: [
         CustomSnackbarComponent,
@@ -184,7 +186,8 @@ import { ContactsListModalComponent } from './contact/list/modal/contacts-list-m
         AttachmentPageComponent,
         AttachmentCreateComponent,
         AttachmentShowModalComponent,
-        ContactsListModalComponent
+        ContactsListModalComponent,
+        ContactModalComponent
     ],
     providers: [ FiltersListService, FoldersService, ActionsService, NotificationService, PrivilegeService ],
     bootstrap: [ AppComponent ]
diff --git a/src/frontend/app/contact/autocomplete/contact-autocomplete.component.ts b/src/frontend/app/contact/autocomplete/contact-autocomplete.component.ts
index ce13bd15d8a790ae85781a12defb068b2dc8b19e..0165766041558fad9c45706fd6f943fbb2582286 100755
--- a/src/frontend/app/contact/autocomplete/contact-autocomplete.component.ts
+++ b/src/frontend/app/contact/autocomplete/contact-autocomplete.component.ts
@@ -11,6 +11,7 @@ import { Observable, of } from 'rxjs';
 import { debounceTime, filter, distinctUntilChanged, tap, switchMap, exhaustMap, catchError, finalize } from 'rxjs/operators';
 import { LatinisePipe } from 'ngx-pipes';
 import { PrivilegeService } from '../../../service/privileges.service';
+import { ContactModalComponent } from '../../administration/contact/modal/contact-modal.component';
 
 @Component({
     selector: 'app-contact-autocomplete',
@@ -219,19 +220,14 @@ export class ContactAutocompleteComponent implements OnInit {
         }
     }
 
-    addItem() {
-        const newElem = {};
+    openContact() {
+        const dialogRef = this.dialog.open(ContactModalComponent, { width : '1200px', maxWidth : '100vw', data: { } });
 
-        newElem[this.key] = this.myControl.value;
-
-        this.http.post('../../rest/tags', { label: newElem[this.key] }).pipe(
-            tap((data: any) => {
-                for (var key in data) {
-                    newElem['id'] = data[key];
-                    this.newIds.push(data[key]);
-                }
-                this.setFormValue(newElem);
-                this.myControl.setValue('');
+        dialogRef.afterClosed().pipe(
+            //filter((data: string) => data === 'ok'),
+            tap((data) => {
+                console.log(data);
+                
             }),
             catchError((err: any) => {
                 this.notify.handleErrors(err);