From 56b8c06b8436174932ea9c0e208fbdc544e29a76 Mon Sep 17 00:00:00 2001 From: Patrick Gebhardt Date: Tue, 23 Jun 2020 23:02:41 +0200 Subject: [PATCH] Add nearby places --- frontend/src/app/app.module.ts | 8 +++-- .../app/components/place/place.component.html | 6 ++++ .../app/components/place/place.component.scss | 28 +++++++++++++++++ .../components/place/place.component.spec.ts | 25 ++++++++++++++++ .../app/components/place/place.component.ts | 20 +++++++++++++ .../region-details.component.html | 6 ++++ .../region-details.component.scss | 22 ++++++++++++++ .../region-details.component.ts | 4 +++ .../src/app/interfaces/places.interface.ts | 20 +++++++++++++ frontend/src/app/services/data.service.ts | 30 +++++++++++++++++++ 10 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 frontend/src/app/components/place/place.component.html create mode 100644 frontend/src/app/components/place/place.component.scss create mode 100644 frontend/src/app/components/place/place.component.spec.ts create mode 100644 frontend/src/app/components/place/place.component.ts create mode 100644 frontend/src/app/interfaces/places.interface.ts diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 44e7c6b..2fcdfc9 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -28,6 +28,7 @@ import { MatChipsModule, MatDialogModule, MatDividerModule, + MatListModule, MatRadioModule, MatSliderModule, MatSlideToggleModule, @@ -48,6 +49,7 @@ import {ShareDialogComponent} from './dialogs/share-dialog/share-dialog.componen import {TeamComponent} from './containers/team/team.component'; import {DeviceDetectorModule} from 'ngx-device-detector'; import {ToggleSliderComponent} from './components/toggle-slider/toggle-slider.component'; +import {PlaceComponent} from './components/place/place.component'; @NgModule({ @@ -67,7 +69,8 @@ import {ToggleSliderComponent} from './components/toggle-slider/toggle-slider.co ShareButtonComponent, ShareDialogComponent, TeamComponent, - ToggleSliderComponent + ToggleSliderComponent, + PlaceComponent ], imports: [ BrowserModule, @@ -97,7 +100,8 @@ import {ToggleSliderComponent} from './components/toggle-slider/toggle-slider.co MatRadioModule, MatSlideToggleModule, MatSliderModule, - MatChipsModule + MatChipsModule, + MatListModule ], providers: [], bootstrap: [AppComponent], diff --git a/frontend/src/app/components/place/place.component.html b/frontend/src/app/components/place/place.component.html new file mode 100644 index 0000000..1074eb6 --- /dev/null +++ b/frontend/src/app/components/place/place.component.html @@ -0,0 +1,6 @@ + + Image of {{place.place_name}} + + diff --git a/frontend/src/app/components/place/place.component.scss b/frontend/src/app/components/place/place.component.scss new file mode 100644 index 0000000..f169642 --- /dev/null +++ b/frontend/src/app/components/place/place.component.scss @@ -0,0 +1,28 @@ +mat-card { + padding: 0; + display: flex; + flex-direction: column; +} + +img { + flex: 0 0 auto; + width: 20rem; + height: 11.25rem; + object-fit: cover; +} + +.footer { + width: 20rem; + padding: 0.5rem; + box-sizing: border-box; + flex: 0 1 auto; + display: flex; + flex-direction: row; + + .name { + flex: 0 1 auto; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } +} diff --git a/frontend/src/app/components/place/place.component.spec.ts b/frontend/src/app/components/place/place.component.spec.ts new file mode 100644 index 0000000..b2c3a0f --- /dev/null +++ b/frontend/src/app/components/place/place.component.spec.ts @@ -0,0 +1,25 @@ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {PlaceComponent} from './place.component'; + +describe('PlaceComponent', () => { + let component: PlaceComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PlaceComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PlaceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/components/place/place.component.ts b/frontend/src/app/components/place/place.component.ts new file mode 100644 index 0000000..6e1097d --- /dev/null +++ b/frontend/src/app/components/place/place.component.ts @@ -0,0 +1,20 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Place} from '../../interfaces/places.interface'; + +@Component({ + selector: 'app-place', + templateUrl: './place.component.html', + styleUrls: ['./place.component.scss'] +}) +export class PlaceComponent implements OnInit { + + @Input() + place: Place; + + constructor() { + } + + ngOnInit() { + } + +} diff --git a/frontend/src/app/containers/region-details/region-details.component.html b/frontend/src/app/containers/region-details/region-details.component.html index f4b9891..c8f1a69 100644 --- a/frontend/src/app/containers/region-details/region-details.component.html +++ b/frontend/src/app/containers/region-details/region-details.component.html @@ -66,6 +66,12 @@ +
+ Places +
+ +
+
diff --git a/frontend/src/app/containers/region-details/region-details.component.scss b/frontend/src/app/containers/region-details/region-details.component.scss index 177cc04..a499753 100644 --- a/frontend/src/app/containers/region-details/region-details.component.scss +++ b/frontend/src/app/containers/region-details/region-details.component.scss @@ -42,6 +42,7 @@ > .more-btn { color: #8f8f8f; + cursor: pointer; } } @@ -66,6 +67,27 @@ } +.places-container { + display: flex; + flex-direction: column; + + > .group-title { + font-size: 1.5rem; + margin-bottom: 1rem; + } + + > .places { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-evenly; + + app-place { + margin: 0.5rem; + } + } +} + .spinner { flex: 1 1 auto; display: flex; diff --git a/frontend/src/app/containers/region-details/region-details.component.ts b/frontend/src/app/containers/region-details/region-details.component.ts index 3480f24..24a35f5 100644 --- a/frontend/src/app/containers/region-details/region-details.component.ts +++ b/frontend/src/app/containers/region-details/region-details.component.ts @@ -4,6 +4,7 @@ import {ActivatedRoute, ParamMap} from '@angular/router'; import {DataService} from '../../services/data.service'; import {switchMap} from 'rxjs/operators'; import {SearchParameter} from '../../interfaces/search-request.interface'; +import {Place} from '../../interfaces/places.interface'; @Component({ @@ -36,6 +37,8 @@ export class RegionDetailsComponent implements AfterViewInit { /** Extend the description text */ isDescExtended = false; + places: Place[] = []; + constructor(private route: ActivatedRoute, private ds: DataService) { } @@ -45,6 +48,7 @@ export class RegionDetailsComponent implements AfterViewInit { ).subscribe((region: Region) => { this.region = region; this.uriRegionName = encodeURI(this.region.name.toLowerCase()); + this.ds.getPlacesByRegion(this.region.region_id).then(places => this.places = places); setTimeout(() => { if (this.container) { this.container.nativeElement.scrollIntoView(); diff --git a/frontend/src/app/interfaces/places.interface.ts b/frontend/src/app/interfaces/places.interface.ts new file mode 100644 index 0000000..b26c93d --- /dev/null +++ b/frontend/src/app/interfaces/places.interface.ts @@ -0,0 +1,20 @@ +export interface Place { + /** The place id */ + place_id: number; + /** The id of the parent region */ + region_id: number; + /** The name of the place in english */ + place_name: string; + /** The longitude position */ + lon: number; + /** The latitude position */ + lat: number; + /** The user rating between 0 and 5 */ + rating: number; + /** Nearby address */ + vicinity: string; + /** Google photo reference */ + photo_reference: string; + /** URL to the image */ + img_url: string; +} diff --git a/frontend/src/app/services/data.service.ts b/frontend/src/app/services/data.service.ts index b83c7ac..c71b429 100644 --- a/frontend/src/app/services/data.service.ts +++ b/frontend/src/app/services/data.service.ts @@ -3,7 +3,11 @@ import {HttpClient, HttpParams} from '@angular/common/http'; import {Preset} from '../interfaces/preset.interface'; import {Result} from '../interfaces/result.interface'; import {Region} from '../interfaces/region.interface'; +import {Place} from '../interfaces/places.interface'; +/** + * The data service handles all API interactions. + */ @Injectable({ providedIn: 'root' }) @@ -16,16 +20,27 @@ export class DataService { constructor(private http: HttpClient) { } + /** + * Get results for specific search query. + * @param query The search query + */ public searchRegions(query: string): Promise { const params = new HttpParams().set('q', query); return this.http.get(this.API_URL + '/search', {params}).toPromise(); } + /** + * Get all search presets. + */ public getAllPresets(): Promise { return this.http.get(this.API_URL + '/search/presets').toPromise(); } + /** + * Gets all regions. + * @param max Limit the returned regions. Selected regions are random. + */ public async getAllRegions(max?: number): Promise { let params = new HttpParams(); if (max) { @@ -38,6 +53,10 @@ export class DataService { return regions; } + /** + * Gets one region by its id. + * @param id The region id + */ public async getRegion(id: number): Promise { if (this.regionCache.has(id)) { return this.regionCache.get(id); @@ -48,8 +67,19 @@ export class DataService { return region; } + + /** + * Returns POIs near the region. + * @param id The regions id + */ + public getPlacesByRegion(id: number): Promise { + return this.http.get(`${this.API_URL}/regions/${id}/nearby`).toPromise(); + } } +/** + * Defines meta data for all region parameters. + */ export const REGION_PARAM_VIS: RegionParamVisLookup = { temperature_mean: { icon: 'wb_sunny',