Add basic details page

This commit is contained in:
Patrick Gebhardt 2020-06-18 02:10:06 +02:00
parent 9b3d6d4800
commit 299e80e5a2
16 changed files with 153 additions and 12 deletions

View File

@ -3,11 +3,13 @@ import {RouterModule, Routes} from '@angular/router';
import {HomeComponent} from './containers/home/home.component'; import {HomeComponent} from './containers/home/home.component';
import {NotfoundComponent} from './containers/notfound/notfound.component'; import {NotfoundComponent} from './containers/notfound/notfound.component';
import {SearchComponent} from './containers/search/search.component'; import {SearchComponent} from './containers/search/search.component';
import {RegionDetailsComponent} from './containers/region-details/region-details.component';
const routes: Routes = [ const routes: Routes = [
{path: 'home', component: HomeComponent}, {path: 'home', component: HomeComponent},
{path: 'search', component: SearchComponent}, {path: 'search', component: SearchComponent},
{path: 'region/:id', component: RegionDetailsComponent},
{path: '', redirectTo: 'home', pathMatch: 'full'}, {path: '', redirectTo: 'home', pathMatch: 'full'},
{path: '**', component: NotfoundComponent} {path: '**', component: NotfoundComponent}
]; ];

View File

@ -11,6 +11,5 @@ export class AppComponent implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
} }
} }

View File

@ -25,6 +25,7 @@ import {MatButtonToggleModule, MatCheckboxModule, MatDividerModule} from '@angul
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {RegionComponent} from './components/region/region.component'; import {RegionComponent} from './components/region/region.component';
import {ResultComponent} from './components/result/result.component'; import {ResultComponent} from './components/result/result.component';
import {RegionDetailsComponent} from './containers/region-details/region-details.component';
@NgModule({ @NgModule({
@ -35,7 +36,8 @@ import {ResultComponent} from './components/result/result.component';
SearchComponent, SearchComponent,
SearchInputComponent, SearchInputComponent,
RegionComponent, RegionComponent,
ResultComponent ResultComponent,
RegionDetailsComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -6,6 +6,8 @@
> .region-img { > .region-img {
flex: 0 0 auto; flex: 0 0 auto;
width: 100%; width: 100%;
height: 15rem;
object-fit: cover;
} }
> .region-footer { > .region-footer {

View File

@ -6,6 +6,8 @@
> .result-img { > .result-img {
flex: 0 0 auto; flex: 0 0 auto;
width: 100%; width: 100%;
height: 15rem;
object-fit: cover;
} }
> .result-footer { > .result-footer {

View File

@ -1,6 +1,6 @@
<app-search-input></app-search-input> <app-search-input></app-search-input>
<h2>Explore the world</h2> <h2>Explore the world</h2>
<div class="region-container"> <div class="region-container">
<app-region *ngFor="let region of regions" [region]="region"></app-region> <app-region (click)="onRegionClick(region)" *ngFor="let region of regions" [region]="region"></app-region>
</div> </div>

View File

@ -14,6 +14,6 @@ app-search-input {
flex-direction: column; flex-direction: column;
> app-region { > app-region {
margin-bottom: 1rem; margin-bottom: 2rem;
} }
} }

View File

@ -1,6 +1,7 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {Region} from '../../interfaces/region.interface'; import {Region} from '../../interfaces/region.interface';
import {DataService} from '../../services/data.service'; import {DataService} from '../../services/data.service';
import {Router} from '@angular/router';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
@ -11,11 +12,14 @@ export class HomeComponent implements OnInit {
regions: Region[]; regions: Region[];
constructor(private ds: DataService) { constructor(private ds: DataService, private router: Router) {
} }
async ngOnInit() { async ngOnInit() {
this.regions = await this.ds.getAllRegions(); this.regions = await this.ds.getAllRegions();
} }
onRegionClick(region: Region) {
this.router.navigate(['/region', region.region_id]).catch(console.log);
}
} }

View File

@ -0,0 +1,14 @@
<div *ngIf="region">
<img class="region-img" src="https://travopti.de/api/v1/regions/{{region.region_id}}/image">
<div class="region-details-header">
<div class="region-title">
<span class="region-country">{{region.country}}</span>
<span class="region-name">{{region.name}}</span>
</div>
</div>
<p class="region-decsription">{{region.description}}</p>
</div>
<div *ngIf="!region" class="spinner">
<mat-spinner></mat-spinner>
</div>

View File

@ -0,0 +1,49 @@
:host {
display: flex;
flex-direction: column;
height: 100%;
}
.region-img {
width: 100%;
object-fit: cover;
height: 10rem;
margin-bottom: 1.5rem;
}
.region-details-header {
display: flex;
flex-direction: row;
> .region-title {
flex: 0 1 auto;
display: flex;
flex-direction: column;
margin: 0.25rem 0;
> .region-name {
font-weight: bold;
font-size: 2rem;
}
> .region-country {
text-transform: uppercase;
font-size: 1.2rem;
}
}
}
.region-decsription {
text-align: justify;
margin: 0.5rem 0;
}
.spinner {
flex: 1 1 auto;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}

View File

@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {RegionDetailsComponent} from './region-details.component';
describe('RegionDetailsComponent', () => {
let component: RegionDetailsComponent;
let fixture: ComponentFixture<RegionDetailsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [RegionDetailsComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RegionDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,25 @@
import {Component, OnInit} from '@angular/core';
import {Region} from '../../interfaces/region.interface';
import {ActivatedRoute, ParamMap} from '@angular/router';
import {DataService} from '../../services/data.service';
import {switchMap} from 'rxjs/operators';
@Component({
selector: 'app-region-details',
templateUrl: './region-details.component.html',
styleUrls: ['./region-details.component.scss']
})
export class RegionDetailsComponent implements OnInit {
region: Region;
constructor(private route: ActivatedRoute, private ds: DataService) {
}
ngOnInit() {
this.route.paramMap.pipe(
switchMap((params: ParamMap) => this.ds.getRegion(parseInt(params.get('id'), 10)))
).subscribe((region: Region) => this.region = region);
}
}

View File

@ -2,9 +2,11 @@
<span #result></span> <span #result></span>
<div *ngIf="results"> <div *ngIf="results && results.length > 0">
<h2>Results ({{results.length}}):</h2> <h2>Results ({{results.length}}):</h2>
<app-result *ngFor="let result of results" [result]="result"></app-result> <div class="result-container">
<app-result (click)="onResultClick(result)" *ngFor="let result of results" [result]="result"></app-result>
</div>
</div> </div>
<div *ngIf="!results" class="spinner"> <div *ngIf="!results" class="spinner">

View File

@ -8,8 +8,13 @@
} }
} }
.resultCard { .result-container {
margin-bottom: 0.5rem; display: flex;
flex-direction: column;
> app-result {
margin-bottom: 2rem;
}
} }
.spinner { .spinner {

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {Result} from '../../interfaces/result.interface'; import {Result} from '../../interfaces/result.interface';
import {DataService} from '../../services/data.service'; import {DataService} from '../../services/data.service';
@ -16,15 +16,25 @@ export class SearchComponent implements OnInit {
@ViewChild('result', {static: false}) @ViewChild('result', {static: false})
resultDiv: ElementRef; resultDiv: ElementRef;
constructor(private route: ActivatedRoute, private ds: DataService) { constructor(private route: ActivatedRoute, private ds: DataService, private router: Router) {
} }
async ngOnInit() { async ngOnInit() {
this.route.queryParams.subscribe(async params => { this.route.queryParams.subscribe(async params => {
this.queryString = params.q; this.queryString = params.q;
this.results = undefined; this.results = undefined;
if (!this.queryString || this.queryString.length === 0) {
this.results = [];
return;
}
this.results = await this.ds.searchRegions(this.queryString); this.results = await this.ds.searchRegions(this.queryString);
this.resultDiv.nativeElement.scrollIntoView({behavior: 'smooth', block: 'start'}); this.resultDiv.nativeElement.scrollIntoView({behavior: 'smooth', block: 'start'});
}); });
} }
onResultClick(result: Result) {
this.router.navigate(['/region', result.region_id]).catch(console.log);
}
} }

View File

@ -2691,7 +2691,7 @@ export const MOCK_REGIONS: Region[] = [
region_id: 6, region_id: 6,
name: 'Sao Paolo', name: 'Sao Paolo',
country: 'Brazil', country: 'Brazil',
description: null, description: 'São Paulo (/ˌsaʊ ˈpaʊloʊ/; Portuguese pronunciation: [sɐ̃w̃ ˈpawlu]) is a municipality in the Southeast Region of Brazil. The metropolis is an alpha global city (as listed by the GaWC) and the most populous city in Brazil, the Americas, the Western Hemisphere and the Southern Hemisphere, besides being the largest Portuguese-speaking city in the world. The municipality is also the world\'s 4th largest city proper by population. The city is the capital of the surrounding state of São Paulo, the most populous and wealthiest state in Brazil. It exerts strong international influences in commerce, finance, arts and entertainment. The name of the city honors the Apostle, Saint Paul of Tarsus. The city\'s metropolitan area, the Greater São Paulo, ranks as the most populous in Brazil and the 12th most populous on Earth. The process of conurbation between the metropolitan areas located around the Greater São Paulo (Campinas, Santos, Sorocaba and São José dos Campos) created the São Paulo Macrometropolis, a megalopolis with more than 30 million inhabitants, one of the most populous urban agglomerations in the world.',
temperature_mean_max: [ temperature_mean_max: [
27.1, 27.1,
28.1, 28.1,