From b5c264b807e92800550ac8a5bebaa649be80771f Mon Sep 17 00:00:00 2001
From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com>
Date: Fri, 15 Jan 2021 18:32:29 +0100
Subject: [PATCH 1/3] feat: add address search with auto-complete

---
 src/app/home/home.component.html              |  1 +
 .../address-autocomplete.component.html       | 16 +++++++++
 .../address-autocomplete.component.scss       | 22 ++++++++++++
 .../address-autocomplete.component.spec.ts    | 25 +++++++++++++
 .../address-autocomplete.component.ts         | 35 +++++++++++++++++++
 src/app/shared/components/index.ts            |  3 ++
 .../shared/service/address.service.spec.ts    | 16 +++++++++
 src/app/shared/service/address.service.ts     | 14 ++++++++
 src/app/shared/shared.module.ts               |  3 +-
 9 files changed, 134 insertions(+), 1 deletion(-)
 create mode 100644 src/app/shared/components/address-autocomplete/address-autocomplete.component.html
 create mode 100644 src/app/shared/components/address-autocomplete/address-autocomplete.component.scss
 create mode 100644 src/app/shared/components/address-autocomplete/address-autocomplete.component.spec.ts
 create mode 100644 src/app/shared/components/address-autocomplete/address-autocomplete.component.ts
 create mode 100644 src/app/shared/service/address.service.spec.ts
 create mode 100644 src/app/shared/service/address.service.ts

diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index 11b58a671..44ce7a91d 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -1,4 +1,5 @@
 <div fxLayout="row" class="content-container">
+  <app-address-autocomplete></app-address-autocomplete>
   <app-structure-list
     (searchEvent)="getStructures($event)"
     [structureList]="structures"
diff --git a/src/app/shared/components/address-autocomplete/address-autocomplete.component.html b/src/app/shared/components/address-autocomplete/address-autocomplete.component.html
new file mode 100644
index 000000000..73a660d26
--- /dev/null
+++ b/src/app/shared/components/address-autocomplete/address-autocomplete.component.html
@@ -0,0 +1,16 @@
+<div class="search-bar">
+  <div>
+    <input
+      id="search-address"
+      type="text"
+      placeholder="ex: 20 rue du lac, Lyon"
+      (input)="onSearchChange($event.target.value)"
+      #searchAddress
+    />
+  </div>
+  <div class="autocomplete-items">
+    <p *ngFor="let hit of data" (click)="selectedResult(hit)" class="autocomplete-item">
+      {{ parseHitToAddress(hit) }}
+    </p>
+  </div>
+</div>
diff --git a/src/app/shared/components/address-autocomplete/address-autocomplete.component.scss b/src/app/shared/components/address-autocomplete/address-autocomplete.component.scss
new file mode 100644
index 000000000..433d3afca
--- /dev/null
+++ b/src/app/shared/components/address-autocomplete/address-autocomplete.component.scss
@@ -0,0 +1,22 @@
+@import '../../../../assets/scss/color';
+
+.search-bar {
+  display: flex;
+  flex-direction: column;
+}
+.autocomplete-items {
+  border: 0.0625rem solid #d4d4d4;
+  border-top: none;
+  border-bottom: none;
+  z-index: 99;
+  background-color: #fff;
+  cursor: pointer;
+}
+.autocomplete-item {
+  margin: 0;
+  padding: 1em 0;
+}
+.autocomplete-item:hover {
+  background-color: #dee6ee;
+  cursor: pointer;
+}
diff --git a/src/app/shared/components/address-autocomplete/address-autocomplete.component.spec.ts b/src/app/shared/components/address-autocomplete/address-autocomplete.component.spec.ts
new file mode 100644
index 000000000..a74f2a401
--- /dev/null
+++ b/src/app/shared/components/address-autocomplete/address-autocomplete.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AddressAutocompleteComponent } from './address-autocomplete.component';
+
+describe('AddressAutocompleteComponent', () => {
+  let component: AddressAutocompleteComponent;
+  let fixture: ComponentFixture<AddressAutocompleteComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ AddressAutocompleteComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(AddressAutocompleteComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts b/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts
new file mode 100644
index 000000000..aead77070
--- /dev/null
+++ b/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts
@@ -0,0 +1,35 @@
+import { Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
+import { AddressService } from '../../service/address.service';
+
+@Component({
+  selector: 'app-address-autocomplete',
+  templateUrl: './address-autocomplete.component.html',
+  styleUrls: ['./address-autocomplete.component.scss'],
+})
+export class AddressAutocompleteComponent {
+  public data = [];
+  @ViewChild('searchAddress', { static: true }) searchAddress: ElementRef;
+  @Output() selectedAddress: EventEmitter<string> = new EventEmitter<string>();
+
+  constructor(private addressService: AddressService) {}
+
+  public onSearchChange(searchString: string) {
+    this.addressService.searchAddress(searchString).subscribe((data) => {
+      this.data = data.hits.hits;
+    });
+  }
+
+  public selectedResult(hit: any): void {
+    const value = this.parseHitToAddress(hit);
+    // Set input value
+    this.searchAddress.nativeElement.value = value;
+    // Reset autocomplete
+    this.data = [];
+    // Emit choosen value
+    this.selectedAddress.emit(value);
+  }
+
+  public parseHitToAddress(hit: any): string {
+    return `${hit._source['data-fr'].properties.numero_str} ${hit._source['data-fr'].properties.voie_str} ${hit._source['data-fr'].properties.commune_str}`;
+  }
+}
diff --git a/src/app/shared/components/index.ts b/src/app/shared/components/index.ts
index 89b310d72..e4d55982f 100644
--- a/src/app/shared/components/index.ts
+++ b/src/app/shared/components/index.ts
@@ -6,6 +6,7 @@ import { SignInModalComponent } from './signin-modal/signin-modal.component';
 import { SvgIconComponent } from './svg-icon/svg-icon.component';
 import { ValidatorFormComponent } from './validator-form/validator-form.component';
 import { CreateAccountFormComponent } from './create-account-form/create-account-form.component';
+import { AddressAutocompleteComponent } from './address-autocomplete/address-autocomplete.component';
 
 // tslint:disable-next-line: max-line-length
 export {
@@ -17,6 +18,7 @@ export {
   SignUpModalComponent,
   SignInModalComponent,
   CreateAccountFormComponent,
+  AddressAutocompleteComponent,
 };
 
 // tslint:disable-next-line:variable-name
@@ -29,4 +31,5 @@ export const SharedComponents = [
   SignUpModalComponent,
   SignInModalComponent,
   CreateAccountFormComponent,
+  AddressAutocompleteComponent,
 ];
diff --git a/src/app/shared/service/address.service.spec.ts b/src/app/shared/service/address.service.spec.ts
new file mode 100644
index 000000000..f0cd890c8
--- /dev/null
+++ b/src/app/shared/service/address.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AddressService } from './address.service';
+
+describe('AddressService', () => {
+  let service: AddressService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(AddressService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/src/app/shared/service/address.service.ts b/src/app/shared/service/address.service.ts
new file mode 100644
index 000000000..38f66f8d1
--- /dev/null
+++ b/src/app/shared/service/address.service.ts
@@ -0,0 +1,14 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class AddressService {
+  constructor(private http: HttpClient) {}
+
+  public searchAddress(searchQuery: string): Observable<any> {
+    return this.http.post<any>(`api/structures/address`, { searchQuery });
+  }
+}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 7a91eef73..2709454bd 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -7,9 +7,10 @@ import { SharedComponents } from './components';
 import { SharedPipes } from './pipes';
 import { SharedDirectives } from './directives';
 import { SvgIconComponent } from './components/svg-icon/svg-icon.component';
+import { AddressAutocompleteComponent } from './components/address-autocomplete/address-autocomplete.component';
 @NgModule({
   imports: [CommonModule, RouterModule, FlexLayoutModule, ReactiveFormsModule],
-  declarations: [...SharedPipes, ...SharedComponents, ...SharedDirectives, SvgIconComponent],
+  declarations: [...SharedPipes, ...SharedComponents, ...SharedDirectives, SvgIconComponent, AddressAutocompleteComponent],
   exports: [
     ...SharedPipes,
     ...SharedComponents,
-- 
GitLab


From b1dba86db8287cb7926e5f6373269d1ff5537ac2 Mon Sep 17 00:00:00 2001
From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com>
Date: Mon, 18 Jan 2021 17:28:48 +0100
Subject: [PATCH 2/3] feat(style): add form-input style

---
 .../address-autocomplete.component.html          |  1 +
 .../address-autocomplete.component.ts            |  3 ++-
 src/assets/scss/_inputs.scss                     | 16 ++++++++++++++++
 src/assets/scss/_shapes.scss                     |  2 +-
 src/styles.scss                                  |  1 +
 5 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/app/shared/components/address-autocomplete/address-autocomplete.component.html b/src/app/shared/components/address-autocomplete/address-autocomplete.component.html
index 73a660d26..537de506d 100644
--- a/src/app/shared/components/address-autocomplete/address-autocomplete.component.html
+++ b/src/app/shared/components/address-autocomplete/address-autocomplete.component.html
@@ -5,6 +5,7 @@
       type="text"
       placeholder="ex: 20 rue du lac, Lyon"
       (input)="onSearchChange($event.target.value)"
+      class="form-input"
       #searchAddress
     />
   </div>
diff --git a/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts b/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts
index aead77070..4e6d5cc97 100644
--- a/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts
+++ b/src/app/shared/components/address-autocomplete/address-autocomplete.component.ts
@@ -7,6 +7,7 @@ import { AddressService } from '../../service/address.service';
   styleUrls: ['./address-autocomplete.component.scss'],
 })
 export class AddressAutocompleteComponent {
+  public readonly AUTOCOMPLETE_NBR = 5;
   public data = [];
   @ViewChild('searchAddress', { static: true }) searchAddress: ElementRef;
   @Output() selectedAddress: EventEmitter<string> = new EventEmitter<string>();
@@ -15,7 +16,7 @@ export class AddressAutocompleteComponent {
 
   public onSearchChange(searchString: string) {
     this.addressService.searchAddress(searchString).subscribe((data) => {
-      this.data = data.hits.hits;
+      this.data = data.hits.hits.slice(0, this.AUTOCOMPLETE_NBR);
     });
   }
 
diff --git a/src/assets/scss/_inputs.scss b/src/assets/scss/_inputs.scss
index dac479e10..e672692f6 100644
--- a/src/assets/scss/_inputs.scss
+++ b/src/assets/scss/_inputs.scss
@@ -1,3 +1,6 @@
+@import './color';
+@import './shapes';
+
 @mixin input-search {
   width: 100%;
   border: none;
@@ -7,3 +10,16 @@
   outline: none;
   font-style: italic;
 }
+
+.form-input {
+  min-width: 290px;
+  background: $grey-6;
+  border: 1px solid $grey-4;
+  box-sizing: border-box;
+  border-radius: $input-radius;
+  height: 40px;
+}
+.form-input:focus {
+  border: 1px solid $blue;
+  outline: none !important;
+}
diff --git a/src/assets/scss/_shapes.scss b/src/assets/scss/_shapes.scss
index fec384566..c85355e0f 100644
--- a/src/assets/scss/_shapes.scss
+++ b/src/assets/scss/_shapes.scss
@@ -2,7 +2,7 @@
 
 $card-radius: 0.625em;
 $bouton-radius: 0.625em;
-$input-radius: 0.3125em;
+$input-radius: 4px;
 $bouton-width: 12.25em;
 $round-bouton-radius: 1.25em;
 $round-radius: 50%;
diff --git a/src/styles.scss b/src/styles.scss
index 3e993cf99..1773ee54c 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -4,6 +4,7 @@
 @import 'assets/scss/color';
 @import 'assets/scss/breakpoint';
 @import 'assets/scss/icons';
+@import 'assets/scss/inputs';
 @import '../node_modules/leaflet.locatecontrol/dist/L.Control.Locate.css';
 
 html {
-- 
GitLab


From 729e20f81813400c0ae24c518c3985d88b373fe9 Mon Sep 17 00:00:00 2001
From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com>
Date: Mon, 18 Jan 2021 17:32:33 +0100
Subject: [PATCH 3/3] fix: remove test component from home

---
 src/app/home/home.component.html | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index 44ce7a91d..11b58a671 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -1,5 +1,4 @@
 <div fxLayout="row" class="content-container">
-  <app-address-autocomplete></app-address-autocomplete>
   <app-structure-list
     (searchEvent)="getStructures($event)"
     [structureList]="structures"
-- 
GitLab