Add details to search results
This commit is contained in:
parent
c8c0b7f900
commit
afb4234ce4
@ -27,6 +27,7 @@ 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';
|
import {RegionDetailsComponent} from './containers/region-details/region-details.component';
|
||||||
import {GraphComponent} from './components/graph/graph.component';
|
import {GraphComponent} from './components/graph/graph.component';
|
||||||
|
import {RegionStatsComponent} from './components/region-stats/region-stats.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -39,7 +40,8 @@ import {GraphComponent} from './components/graph/graph.component';
|
|||||||
RegionComponent,
|
RegionComponent,
|
||||||
ResultComponent,
|
ResultComponent,
|
||||||
RegionDetailsComponent,
|
RegionDetailsComponent,
|
||||||
GraphComponent
|
GraphComponent,
|
||||||
|
RegionStatsComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
<table>
|
||||||
|
<tr *ngFor="let prop of shownKeys">
|
||||||
|
<td>
|
||||||
|
<div class="cell space">
|
||||||
|
<mat-icon>{{PROPERTY_VIS_DEF[prop].icon}}</mat-icon>
|
||||||
|
<span>{{prop|translate}}:</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="cell right">
|
||||||
|
<span>{{region[prop] ? (region[prop]|number:'1.2-2') : 'N/A'}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="cell">
|
||||||
|
<span>{{PROPERTY_VIS_DEF[prop].unit}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
.cell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.space {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> mat-icon {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {RegionStatsComponent} from './region-stats.component';
|
||||||
|
|
||||||
|
describe('RegionStatsComponent', () => {
|
||||||
|
let component: RegionStatsComponent;
|
||||||
|
let fixture: ComponentFixture<RegionStatsComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [RegionStatsComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RegionStatsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
|
import {Region} from '../../interfaces/region.interface';
|
||||||
|
import {SearchParameter} from '../../interfaces/search-request.interface';
|
||||||
|
import {REGION_PARAM_VIS} from '../../services/data.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-region-stats',
|
||||||
|
templateUrl: './region-stats.component.html',
|
||||||
|
styleUrls: ['./region-stats.component.scss']
|
||||||
|
})
|
||||||
|
export class RegionStatsComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
region: Region;
|
||||||
|
@Input()
|
||||||
|
shownKeys: SearchParameter[];
|
||||||
|
|
||||||
|
/** Contains the visual definitions */
|
||||||
|
readonly PROPERTY_VIS_DEF = REGION_PARAM_VIS;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
> .region-name {
|
> .region-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: large;
|
font-size: larger;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<div class="result-mat-card">
|
<div class="result-mat-card">
|
||||||
<img class="result-img" src="https://travopti.de/api/v1/regions/{{result.region_id}}/image">
|
<img class="result-img" src="https://travopti.de/api/v1/regions/{{result.region_id}}/image">
|
||||||
<div class="result-footer">
|
<div class="result-title">
|
||||||
<div class="result-title">
|
<div class="result-name">
|
||||||
<span class="result-name">{{result.name}}</span>
|
<span class="result-name">{{result.name}}</span>
|
||||||
<span class="result-country">| {{result.country}}</span>
|
<span class="result-country">| {{result.country}}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -12,4 +12,26 @@
|
|||||||
<mat-icon>share</mat-icon>
|
<mat-icon>share</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="result-details">
|
||||||
|
<table>
|
||||||
|
<tr *ngFor="let score of result.scores">
|
||||||
|
<td>
|
||||||
|
<div class="cell space">
|
||||||
|
<mat-icon>{{PROPERTY_VIS_DEF[score.type].icon}}</mat-icon>
|
||||||
|
<span>{{score.type|translate}}:</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="cell right">
|
||||||
|
<span>{{score.value ? (score.value|number:'1.2-2') : 'N/A'}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="cell">
|
||||||
|
<span>{{PROPERTY_VIS_DEF[score.type].unit}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -10,12 +10,13 @@
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .result-footer {
|
> .result-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
> .result-title {
|
> .result-name {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -29,12 +30,32 @@
|
|||||||
|
|
||||||
> .result-name {
|
> .result-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: large;
|
font-size: larger;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .result-details {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.space {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> mat-icon {
|
||||||
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
import {Result} from '../../interfaces/result.interface';
|
import {Result} from '../../interfaces/result.interface';
|
||||||
|
import {REGION_PARAM_VIS} from '../../services/data.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-result',
|
selector: 'app-result',
|
||||||
@ -11,6 +12,9 @@ export class ResultComponent implements OnInit {
|
|||||||
@Input()
|
@Input()
|
||||||
result: Result;
|
result: Result;
|
||||||
|
|
||||||
|
/** Contains the visual definitions */
|
||||||
|
readonly PROPERTY_VIS_DEF = REGION_PARAM_VIS;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,35 +19,13 @@
|
|||||||
<span *ngIf="isDescExtended">{{region.description.substr(DESC_CUT_POINT)}}</span>
|
<span *ngIf="isDescExtended">{{region.description.substr(DESC_CUT_POINT)}}</span>
|
||||||
</p>
|
</p>
|
||||||
<div class="region-stats-group">
|
<div class="region-stats-group">
|
||||||
<div>
|
<app-region-stats [region]="region" [shownKeys]="SHOWN_PROPS"></app-region-stats>
|
||||||
<table>
|
|
||||||
<tr *ngFor="let prop of SHOWN_PROPS">
|
|
||||||
<td>
|
|
||||||
<div class="cell">
|
|
||||||
<mat-icon>{{prop.icon}}</mat-icon>
|
|
||||||
<span>{{prop.property|translate}}:</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="cell right">
|
|
||||||
<span>{{region[prop.property].toFixed(2)}}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="cell">
|
|
||||||
<span>{{prop.unit}}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="region-stats-group">
|
<div *ngIf="region.temperature_mean_max && region.temperature_mean_max[0]" class="region-stats-group">
|
||||||
<span class="group-title">Max Temperatures [°C]</span>
|
<span class="group-title">Max Temperatures [°C]</span>
|
||||||
<app-graph [monthlyData]="region.temperature_mean_max" class="graph"></app-graph>
|
<app-graph [monthlyData]="region.temperature_mean_max" class="graph"></app-graph>
|
||||||
</div>
|
</div>
|
||||||
<div class="region-stats-group">
|
<div *ngIf="region.precipitation && region.precipitation[0]" class="region-stats-group">
|
||||||
<span class="group-title">Precipitation [mm]</span>
|
<span class="group-title">Precipitation [mm]</span>
|
||||||
<app-graph [monthlyData]="region.precipitation" class="graph"></app-graph>
|
<app-graph [monthlyData]="region.precipitation" class="graph"></app-graph>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -59,21 +59,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
> mat-icon {
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -3,12 +3,8 @@ import {Region} from '../../interfaces/region.interface';
|
|||||||
import {ActivatedRoute, ParamMap} from '@angular/router';
|
import {ActivatedRoute, ParamMap} from '@angular/router';
|
||||||
import {DataService} from '../../services/data.service';
|
import {DataService} from '../../services/data.service';
|
||||||
import {switchMap} from 'rxjs/operators';
|
import {switchMap} from 'rxjs/operators';
|
||||||
|
import {SearchParameter} from '../../interfaces/search-request.interface';
|
||||||
|
|
||||||
interface VisualRegionPropDef {
|
|
||||||
property: string;
|
|
||||||
icon: string;
|
|
||||||
unit: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-region-details',
|
selector: 'app-region-details',
|
||||||
@ -20,32 +16,14 @@ export class RegionDetailsComponent implements OnInit {
|
|||||||
/** Cut descriptions after x chars */
|
/** Cut descriptions after x chars */
|
||||||
readonly DESC_CUT_POINT = 300;
|
readonly DESC_CUT_POINT = 300;
|
||||||
/** Region property to show in view */
|
/** Region property to show in view */
|
||||||
readonly SHOWN_PROPS: VisualRegionPropDef[] = [
|
readonly SHOWN_PROPS: SearchParameter[] = [
|
||||||
{
|
SearchParameter.AVERAGE_PER_DAY_COSTS,
|
||||||
property: 'average_per_day_costs',
|
SearchParameter.ACCOMMODATION_COSTS,
|
||||||
icon: 'euro',
|
SearchParameter.FOOD_COSTS,
|
||||||
unit: '€/day',
|
SearchParameter.WATER_COSTS,
|
||||||
},
|
SearchParameter.ALCOHOL_COSTS,
|
||||||
{
|
SearchParameter.LOCAL_TRANSPORTATION_COSTS,
|
||||||
property: 'food_costs',
|
SearchParameter.ENTERTAINMENT_COSTS,
|
||||||
icon: 'local_dining',
|
|
||||||
unit: '€/day',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
property: 'alcohol_costs',
|
|
||||||
icon: 'local_bar',
|
|
||||||
unit: '€/day',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
property: 'local_transportation_costs',
|
|
||||||
icon: 'commute',
|
|
||||||
unit: '€/day',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
property: 'entertainment_costs',
|
|
||||||
icon: 'local_activity',
|
|
||||||
unit: '€/day',
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Current region */
|
/** Current region */
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
> app-result {
|
> app-result {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,25 +1,32 @@
|
|||||||
export enum SearchParam {
|
|
||||||
FROM = 'from',
|
|
||||||
TO = 'to',
|
|
||||||
TEMPERATURE = 'temperature',
|
|
||||||
PRECIPITATION = 'precipitation',
|
|
||||||
RAINDAYS = 'raindays',
|
|
||||||
HUMIDITY = 'humidity',
|
|
||||||
SUNHOURS = 'sunhours',
|
|
||||||
ALCOHOL = 'alcohol',
|
|
||||||
FOOD = 'food'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Query {
|
export interface Query {
|
||||||
from: number;
|
from: number;
|
||||||
to: number;
|
to: number;
|
||||||
price?: number[];
|
temperature_mean_max?: number[];
|
||||||
exclude_region_ids?: number[];
|
|
||||||
temperature?: number[];
|
|
||||||
precipitation?: number[];
|
precipitation?: number[];
|
||||||
raindays?: number[];
|
rain_days?: number[];
|
||||||
humidity?: number[];
|
humidity?: number[];
|
||||||
sunhours?: number[];
|
sun_hours?: number[];
|
||||||
alcohol?: number[];
|
alcohol_costs?: number[];
|
||||||
food?: number[];
|
food_costs?: number[];
|
||||||
|
local_transportation_costs: number[];
|
||||||
|
entertainment_costs: number[];
|
||||||
|
accommodation_costs: number[];
|
||||||
|
average_per_day_costs: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SearchParameter {
|
||||||
|
TEMP_MEAN = 'temperature_mean',
|
||||||
|
TEMP_MEAN_MIN = 'temperature_mean_min',
|
||||||
|
TEMP_MEAN_MAX = 'temperature_mean_max',
|
||||||
|
PRECIPITATION = 'precipitation',
|
||||||
|
HUMIDITY = 'humidity',
|
||||||
|
SUN_HOURS = 'sun_hours',
|
||||||
|
RAIN_DAYS = 'rain_days',
|
||||||
|
FOOD_COSTS = 'food_costs',
|
||||||
|
ALCOHOL_COSTS = 'alcohol_costs',
|
||||||
|
WATER_COSTS = 'water_costs',
|
||||||
|
LOCAL_TRANSPORTATION_COSTS = 'local_transportation_costs',
|
||||||
|
ENTERTAINMENT_COSTS = 'entertainment_costs',
|
||||||
|
ACCOMMODATION_COSTS = 'accommodation_costs',
|
||||||
|
AVERAGE_PER_DAY_COSTS = 'average_per_day_costs'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,29 +17,106 @@ export class DataService {
|
|||||||
public searchRegions(query: string): Promise<Result[]> {
|
public searchRegions(query: string): Promise<Result[]> {
|
||||||
const params = new HttpParams().set('q', query);
|
const params = new HttpParams().set('q', query);
|
||||||
|
|
||||||
console.log(params);
|
|
||||||
|
|
||||||
return this.http.get<Result[]>(this.API_URL + '/search', {params}).toPromise();
|
return this.http.get<Result[]>(this.API_URL + '/search', {params}).toPromise();
|
||||||
// return new Promise<Result[]>(resolve => {
|
// return new Promise<Result[]>(resolve => {
|
||||||
// resolve(MOCK_RESULT);
|
// setTimeout(() => {
|
||||||
|
// resolve(MOCK_RESULT);
|
||||||
|
// }, 100);
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAllPresets(): Promise<Preset[]> {
|
public getAllPresets(): Promise<Preset[]> {
|
||||||
return this.http.get<Preset[]>(this.API_URL + '/search/presets').toPromise();
|
return this.http.get<Preset[]>(this.API_URL + '/search/presets').toPromise();
|
||||||
// return new Promise<Preset[]>(resolve => {
|
// return new Promise<Preset[]>(resolve => {
|
||||||
// resolve(MOCK_PRESETS);
|
// setTimeout(() => {
|
||||||
|
// resolve(MOCK_PRESETS);
|
||||||
|
// }, 100);
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAllRegions(): Promise<Region[]> {
|
public getAllRegions(): Promise<Region[]> {
|
||||||
return this.http.get<Region[]>(this.API_URL + '/regions').toPromise();
|
return this.http.get<Region[]>(this.API_URL + '/regions').toPromise();
|
||||||
// return new Promise<Region[]>(resolve => {
|
// return new Promise<Region[]>(resolve => {
|
||||||
// resolve(MOCK_REGIONS);
|
// setTimeout(() => {
|
||||||
|
// resolve(MOCK_REGIONS);
|
||||||
|
// }, 100);
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
public getRegion(id: number): Promise<Region> {
|
public getRegion(id: number): Promise<Region> {
|
||||||
return this.http.get<Region>(`${this.API_URL}/regions/${id}`).toPromise();
|
return this.http.get<Region>(`${this.API_URL}/regions/${id}`).toPromise();
|
||||||
|
// return new Promise<Region>(resolve => {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// resolve(MOCK_REGIONS.find(region => region.region_id === id));
|
||||||
|
// }, 100);
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const REGION_PARAM_VIS: RegionParamVisLookup = {
|
||||||
|
temperature_mean: {
|
||||||
|
icon: 'wb_sunny',
|
||||||
|
unit: '°C'
|
||||||
|
},
|
||||||
|
temperature_mean_min: {
|
||||||
|
icon: 'wb_sunny',
|
||||||
|
unit: '°C'
|
||||||
|
},
|
||||||
|
temperature_mean_max: {
|
||||||
|
icon: 'wb_sunny',
|
||||||
|
unit: '°C'
|
||||||
|
},
|
||||||
|
precipitation: {
|
||||||
|
icon: 'opacity',
|
||||||
|
unit: 'mm'
|
||||||
|
},
|
||||||
|
humidity: {
|
||||||
|
icon: 'grain',
|
||||||
|
unit: '%'
|
||||||
|
},
|
||||||
|
sun_hours: {
|
||||||
|
icon: 'flare',
|
||||||
|
unit: 'h'
|
||||||
|
},
|
||||||
|
rain_days: {
|
||||||
|
icon: 'date_range',
|
||||||
|
unit: ''
|
||||||
|
},
|
||||||
|
food_costs: {
|
||||||
|
icon: 'local_dining',
|
||||||
|
unit: '€/day'
|
||||||
|
},
|
||||||
|
alcohol_costs: {
|
||||||
|
icon: 'local_bar',
|
||||||
|
unit: '€/day'
|
||||||
|
},
|
||||||
|
water_costs: {
|
||||||
|
icon: 'local_cafe',
|
||||||
|
unit: '€/day'
|
||||||
|
},
|
||||||
|
local_transportation_costs: {
|
||||||
|
icon: 'commute',
|
||||||
|
unit: '€/day'
|
||||||
|
},
|
||||||
|
entertainment_costs: {
|
||||||
|
icon: 'local_activity',
|
||||||
|
unit: '€/day'
|
||||||
|
},
|
||||||
|
accommodation_costs: {
|
||||||
|
icon: 'hotel',
|
||||||
|
unit: '€/day'
|
||||||
|
},
|
||||||
|
average_per_day_costs: {
|
||||||
|
icon: 'euro',
|
||||||
|
unit: '€/day'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface RegionParamVisLookup {
|
||||||
|
[key: string]: RegionParamVis;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RegionParamVis {
|
||||||
|
icon: string;
|
||||||
|
unit: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"temperature_mean_max": "Temperature Average",
|
"temperature_mean_max": "Max Temperature Average",
|
||||||
"temperature": "Temperature",
|
"temperature": "Temperature",
|
||||||
"rain_days": "Rainy days",
|
"rain_days": "Rainy days",
|
||||||
"sun_hours": "Sunny hours",
|
"sun_hours": "Sunny hours",
|
||||||
@ -7,10 +7,12 @@
|
|||||||
"humidity": "Humidity",
|
"humidity": "Humidity",
|
||||||
"alcohol_costs": "Alcohol costs",
|
"alcohol_costs": "Alcohol costs",
|
||||||
"food_costs": "Food costs",
|
"food_costs": "Food costs",
|
||||||
|
"water_costs": "Water costs",
|
||||||
"cheap_alcohol": "Cheap alcohol",
|
"cheap_alcohol": "Cheap alcohol",
|
||||||
"local_transportation_costs": "Public transport",
|
"local_transportation_costs": "Public transport",
|
||||||
"average_per_day_costs": "Average total costs",
|
"average_per_day_costs": "Average total costs",
|
||||||
"entertainment_costs": "Entertainment costs",
|
"entertainment_costs": "Entertainment costs",
|
||||||
|
"accommodation_costs": "Accommodation costs",
|
||||||
"cheap_food": "Cheap food",
|
"cheap_food": "Cheap food",
|
||||||
"cheap_water": "Cheap water",
|
"cheap_water": "Cheap water",
|
||||||
"cheap_transportations": "Cheap public transport",
|
"cheap_transportations": "Cheap public transport",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user