diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index a949db3..9113578 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -1,11 +1,13 @@
-import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
+import {NgModule} from '@angular/core';
+import {RouterModule, Routes} from '@angular/router';
import {HomeComponent} from './containers/home/home.component';
import {NotfoundComponent} from './containers/notfound/notfound.component';
+import {SearchComponent} from './containers/search/search.component';
const routes: Routes = [
{path: 'home', component: HomeComponent},
+ {path: 'search', component: SearchComponent},
{path: '', redirectTo: 'home', pathMatch: 'full'},
{path: '**', component: NotfoundComponent}
];
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 1ab64de..914daa8 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -1,25 +1,30 @@
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
+import {BrowserModule} from '@angular/platform-browser';
+import {NgModule} from '@angular/core';
-import { AppRoutingModule } from './app-routing.module';
-import { AppComponent } from './app.component';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import {AppRoutingModule} from './app-routing.module';
+import {AppComponent} from './app.component';
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatToolbarModule} from '@angular/material/toolbar';
import {MatIconModule} from '@angular/material/icon';
import {MatButtonModule} from '@angular/material/button';
import {MatSidenavModule} from '@angular/material/sidenav';
-import { HomeComponent } from './containers/home/home.component';
+import {HomeComponent} from './containers/home/home.component';
import {MatCardModule} from '@angular/material/card';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input';
import {MatSelectModule} from '@angular/material/select';
-import { NotfoundComponent } from './containers/notfound/notfound.component';
+import {NotfoundComponent} from './containers/notfound/notfound.component';
+import {SearchComponent} from './containers/search/search.component';
+import {SearchInputComponent} from './components/search-input/search-input.component';
+import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
- NotfoundComponent
+ NotfoundComponent,
+ SearchComponent,
+ SearchInputComponent
],
imports: [
BrowserModule,
@@ -32,7 +37,8 @@ import { NotfoundComponent } from './containers/notfound/notfound.component';
MatCardModule,
MatFormFieldModule,
MatInputModule,
- MatSelectModule
+ MatSelectModule,
+ MatProgressSpinnerModule
],
providers: [],
bootstrap: [AppComponent]
diff --git a/frontend/src/app/components/search-input/search-input.component.html b/frontend/src/app/components/search-input/search-input.component.html
new file mode 100644
index 0000000..69a84cd
--- /dev/null
+++ b/frontend/src/app/components/search-input/search-input.component.html
@@ -0,0 +1,28 @@
+
+
+ Search
+
+
+
+
+ Start
+
+
+
+ End
+
+
+
+ Price
+
+ Budget
+ Mid-Range
+ Luxury
+
+
+
+
diff --git a/frontend/src/app/components/search-input/search-input.component.scss b/frontend/src/app/components/search-input/search-input.component.scss
new file mode 100644
index 0000000..886ce23
--- /dev/null
+++ b/frontend/src/app/components/search-input/search-input.component.scss
@@ -0,0 +1,4 @@
+.search-container {
+ display: flex;
+ flex-direction: column;
+}
diff --git a/frontend/src/app/components/search-input/search-input.component.spec.ts b/frontend/src/app/components/search-input/search-input.component.spec.ts
new file mode 100644
index 0000000..4483c5d
--- /dev/null
+++ b/frontend/src/app/components/search-input/search-input.component.spec.ts
@@ -0,0 +1,25 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {SearchInputComponent} from './search-input.component';
+
+describe('SearchInputComponent', () => {
+ let component: SearchInputComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [SearchInputComponent]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SearchInputComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/components/search-input/search-input.component.ts b/frontend/src/app/components/search-input/search-input.component.ts
new file mode 100644
index 0000000..a341f28
--- /dev/null
+++ b/frontend/src/app/components/search-input/search-input.component.ts
@@ -0,0 +1,28 @@
+import {Component, OnInit} from '@angular/core';
+import {Router} from '@angular/router';
+import {Query} from '../../interfaces/search-request.interface';
+import {objToBase64} from '../../utils/base64conversion';
+
+@Component({
+ selector: 'app-search-input',
+ templateUrl: './search-input.component.html',
+ styleUrls: ['./search-input.component.scss']
+})
+export class SearchInputComponent implements OnInit {
+
+ constructor(private router: Router) {
+ }
+
+ ngOnInit() {
+ }
+
+ async onSearch() {
+ const query: Query = {
+ from: Date.now(),
+ to: Date.now(),
+ };
+
+ await this.router.navigate(['/search'], {queryParams: {q: objToBase64(query)}});
+ }
+
+}
diff --git a/frontend/src/app/containers/home/home.component.html b/frontend/src/app/containers/home/home.component.html
index 4a9c6b7..f4d1db7 100644
--- a/frontend/src/app/containers/home/home.component.html
+++ b/frontend/src/app/containers/home/home.component.html
@@ -1,28 +1 @@
-
-
- Search
-
-
-
-
- Start
-
-
-
- End
-
-
-
- Price
-
- Budget
- Mid-Range
- Luxury
-
-
-
-
+
diff --git a/frontend/src/app/containers/home/home.component.scss b/frontend/src/app/containers/home/home.component.scss
index 825a777..0bd77a1 100644
--- a/frontend/src/app/containers/home/home.component.scss
+++ b/frontend/src/app/containers/home/home.component.scss
@@ -2,8 +2,3 @@
margin: 0;
box-sizing: border-box;
}
-
-.search-container {
- display: flex;
- flex-direction: column;
-}
diff --git a/frontend/src/app/containers/search/search.component.html b/frontend/src/app/containers/search/search.component.html
new file mode 100644
index 0000000..c1f8e36
--- /dev/null
+++ b/frontend/src/app/containers/search/search.component.html
@@ -0,0 +1,12 @@
+
+
+
+ Suchergebnisse ({{results.length}}):
+
+ - {{result.name}} ({{result.score}})
+
+
+
+
+
+
diff --git a/frontend/src/app/containers/search/search.component.scss b/frontend/src/app/containers/search/search.component.scss
new file mode 100644
index 0000000..56f5c03
--- /dev/null
+++ b/frontend/src/app/containers/search/search.component.scss
@@ -0,0 +1,17 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+
+ > * {
+ margin-bottom: 1rem;
+ }
+}
+
+.spinner {
+ flex: 1 1 auto;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+}
diff --git a/frontend/src/app/containers/search/search.component.spec.ts b/frontend/src/app/containers/search/search.component.spec.ts
new file mode 100644
index 0000000..5a3cb0f
--- /dev/null
+++ b/frontend/src/app/containers/search/search.component.spec.ts
@@ -0,0 +1,25 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {SearchComponent} from './search.component';
+
+describe('SearchComponent', () => {
+ let component: SearchComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [SearchComponent]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SearchComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/containers/search/search.component.ts b/frontend/src/app/containers/search/search.component.ts
new file mode 100644
index 0000000..3ff301e
--- /dev/null
+++ b/frontend/src/app/containers/search/search.component.ts
@@ -0,0 +1,30 @@
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
+import {Result} from '../../interfaces/result.interface';
+import {MOCK_RESULT} from '../../mock/mock-data';
+
+@Component({
+ selector: 'app-search',
+ templateUrl: './search.component.html',
+ styleUrls: ['./search.component.scss']
+})
+export class SearchComponent implements OnInit {
+
+ queryString: string;
+ results: Result[];
+
+ constructor(private route: ActivatedRoute) {
+ }
+
+ ngOnInit() {
+ this.route.queryParams.subscribe(params => {
+ this.queryString = params.q;
+ });
+
+ // Mock results
+ setTimeout(() => {
+ this.results = MOCK_RESULT;
+ }, 1000);
+
+ }
+}
diff --git a/frontend/src/app/interfaces/result.interface.ts b/frontend/src/app/interfaces/result.interface.ts
index 1ca48be..260e03c 100644
--- a/frontend/src/app/interfaces/result.interface.ts
+++ b/frontend/src/app/interfaces/result.interface.ts
@@ -1,15 +1,14 @@
-import {SearchParam} from './search-request.interface';
-
/** Represents the structure of one search result. */
export interface Result {
- region_id: string;
- region_name: string;
+ region_id: number;
+ name: string;
+ country_id: number;
score: number;
scores: Score[];
}
export interface Score {
- type: SearchParam;
+ type: string;
value: number;
score: number;
}
diff --git a/frontend/src/app/interfaces/search-request.interface.ts b/frontend/src/app/interfaces/search-request.interface.ts
index 1095fb6..598f1f3 100644
--- a/frontend/src/app/interfaces/search-request.interface.ts
+++ b/frontend/src/app/interfaces/search-request.interface.ts
@@ -10,7 +10,7 @@ export enum SearchParam {
FOOD = 'food'
}
-export interface SearchParams {
+export interface Query {
from: number;
to: number;
price?: number[];
diff --git a/frontend/src/app/mock/mock-data.ts b/frontend/src/app/mock/mock-data.ts
new file mode 100644
index 0000000..c14c875
--- /dev/null
+++ b/frontend/src/app/mock/mock-data.ts
@@ -0,0 +1,242 @@
+import {Result} from '../interfaces/result.interface';
+
+export const MOCK_RESULT: Result[] = [
+ {
+ region_id: 24,
+ country_id: 20,
+ name: 'Kuala Lumpur',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 28.1,
+ score: 10
+ },
+ {
+ type: 'raindays',
+ value: 13.8,
+ score: 7.5
+ }
+ ],
+ score: 8.75
+ },
+ {
+ region_id: 10,
+ country_id: 7,
+ name: 'Shanghai',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 24.8,
+ score: 6.3
+ },
+ {
+ type: 'raindays',
+ value: 8.6,
+ score: 9.4
+ },
+ {
+ type: 'sunhours',
+ value: 151.2,
+ score: 2.2
+ }
+ ],
+ score: 5.97
+ },
+ {
+ region_id: 3,
+ country_id: 2,
+ name: 'Sydney',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 16.8,
+ score: 0
+ },
+ {
+ type: 'raindays',
+ value: 6.4,
+ score: 8.2
+ },
+ {
+ type: 'sunhours',
+ value: 245.8,
+ score: 9.5
+ }
+ ],
+ score: 5.9
+ },
+ {
+ region_id: 9,
+ country_id: 7,
+ name: 'Peking',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 21.1,
+ score: 4.2
+ },
+ {
+ type: 'raindays',
+ value: 5.4,
+ score: 7.1
+ },
+ {
+ type: 'sunhours',
+ value: 199,
+ score: 6
+ }
+ ],
+ score: 5.77
+ },
+ {
+ region_id: 7,
+ country_id: 5,
+ name: 'Toronto',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 16.8,
+ score: 1.2
+ },
+ {
+ type: 'raindays',
+ value: 8.4,
+ score: 9.3
+ },
+ {
+ type: 'sunhours',
+ value: 206.4,
+ score: 6.2
+ }
+ ],
+ score: 5.57
+ },
+ {
+ region_id: 2,
+ country_id: 2,
+ name: 'Melbourne',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 12.3,
+ score: 0
+ },
+ {
+ type: 'raindays',
+ value: 8.3,
+ score: 10
+ },
+ {
+ type: 'sunhours',
+ value: 187.4,
+ score: 5.1
+ }
+ ],
+ score: 5.03
+ },
+ {
+ region_id: 12,
+ country_id: 9,
+ name: 'Kairo',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 27.9,
+ score: 8.9
+ },
+ {
+ type: 'raindays',
+ value: 0,
+ score: 1.1
+ }
+ ],
+ score: 5
+ },
+ {
+ region_id: 13,
+ country_id: 10,
+ name: 'London',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 16,
+ score: 0
+ },
+ {
+ type: 'raindays',
+ value: 8.6,
+ score: 9.6
+ },
+ {
+ type: 'sunhours',
+ value: 142.4,
+ score: 1.9
+ }
+ ],
+ score: 3.83
+ },
+ {
+ region_id: 6,
+ country_id: 4,
+ name: 'Sao Paolo',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 19.6,
+ score: 0.8
+ },
+ {
+ type: 'raindays',
+ value: 4.6,
+ score: 6
+ }
+ ],
+ score: 3.4
+ },
+ {
+ region_id: 11,
+ country_id: 8,
+ name: 'Bogota',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 13.7,
+ score: 0
+ },
+ {
+ type: 'raindays',
+ value: 9.1,
+ score: 9.8
+ },
+ {
+ type: 'sunhours',
+ value: 121.2,
+ score: 0.1
+ }
+ ],
+ score: 3.3
+ },
+ {
+ region_id: 18,
+ country_id: 15,
+ name: 'Reykjavik',
+ scores: [
+ {
+ type: 'temperature_mean',
+ value: 8.6,
+ score: 0
+ },
+ {
+ type: 'raindays',
+ value: 13.5,
+ score: 7.4
+ },
+ {
+ type: 'sunhours',
+ value: 135.1,
+ score: 1.7
+ }
+ ],
+ score: 3.03
+ }
+];
diff --git a/frontend/src/app/services/data.service.ts b/frontend/src/app/services/data.service.ts
index d9714a1..e29dbdf 100644
--- a/frontend/src/app/services/data.service.ts
+++ b/frontend/src/app/services/data.service.ts
@@ -2,7 +2,6 @@ import {Injectable} from '@angular/core';
import {HttpClient, HttpParams} from '@angular/common/http';
import {Preset} from '../interfaces/preset.interface';
import {Result} from '../interfaces/result.interface';
-import {SearchParams} from '../interfaces/search-request.interface';
import {Region} from '../interfaces/region.interface';
@Injectable({
@@ -15,9 +14,9 @@ export class DataService {
constructor(private http: HttpClient) {
}
- public searchRegions(searchParams: SearchParams): Promise {
+ public searchRegions(query: string): Promise {
const params = new HttpParams();
- params.append('q', btoa(JSON.stringify(searchParams)));
+ params.append('q', query);
return this.http.get(this.API_URL + 'search', {params}).toPromise();
}
diff --git a/frontend/src/app/utils/base64conversion.ts b/frontend/src/app/utils/base64conversion.ts
new file mode 100644
index 0000000..e10d40d
--- /dev/null
+++ b/frontend/src/app/utils/base64conversion.ts
@@ -0,0 +1,15 @@
+/**
+ * Encodes an object as base64 string.
+ * @param obj The object to encode
+ */
+export function objToBase64(obj: object): string {
+ return btoa(JSON.stringify(obj));
+}
+
+/**
+ * Decodes a base64 encoded object.
+ * @param base64 Encoded object
+ */
+export function base64ToObj(base64: string): object {
+ return JSON.parse(atob(base64));
+}