wording and some layout
This commit is contained in:
parent
2077aeebf8
commit
d19a76939b
@ -1,5 +1,5 @@
|
||||
<mat-chip-list>
|
||||
<!--suppress AngularInvalidExpressionResultType -->
|
||||
<mat-chip (click)="onChipClick(tag)" *ngFor="let tag of availableTags" [color]="isSelected(tag) ? 'accent' : 'none'"
|
||||
selected>{{tag}}</mat-chip>
|
||||
selected>{{tag|translate}}</mat-chip>
|
||||
</mat-chip-list>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<div class="region-mat-card">
|
||||
<img alt="Picture of {{region.name}}" class="region-img"
|
||||
src="https://travopti.de/api/v1/regions/{{region.region_id}}/image">
|
||||
src="https://travopti.de/api/v1/regions/{{region.region_id}}/image">
|
||||
<div class="region-footer">
|
||||
<div class="region-title">
|
||||
<span class="region-name">{{region.name}}</span>
|
||||
@ -9,4 +9,4 @@
|
||||
<app-bookmark-button [region]="region"></app-bookmark-button>
|
||||
<app-share-button [region]="region"></app-share-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
<div class="result-mat-card">
|
||||
<img alt="Picture of {{result.name}}" class="result-img"
|
||||
src="https://travopti.de/api/v1/regions/{{result.region_id}}/image">
|
||||
src="https://travopti.de/api/v1/regions/{{result.region_id}}/image">
|
||||
<div class="result-title">
|
||||
<div class="result-header">
|
||||
<span class="result-name">{{result.name}}<span *ngIf="debug"> ({{result.score}})</span></span>
|
||||
@ -17,6 +17,7 @@
|
||||
</div>
|
||||
<mat-divider *ngIf="result.scores.length > 0"></mat-divider>
|
||||
<div class="searched-params">
|
||||
<div class="result-desc">Estimated values for your choosen travel dates</div>
|
||||
<table>
|
||||
<tr *ngFor="let score of result.scores" [ngClass]="{'undefined': score.value == undefined}">
|
||||
<td>
|
||||
@ -27,7 +28,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell right">
|
||||
<span>{{score.value != undefined ? (score.value|number:'1.2-2') : 'N/A'}}</span>
|
||||
<span>{{score.value != undefined ? (score.value|number:PROPERTY_VIS_DEF[score.type].decimals) : 'N/A'}}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@ -44,4 +45,4 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4,33 +4,33 @@
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
|
||||
> .result-img {
|
||||
>.result-img {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
height: 15rem;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
> .result-title {
|
||||
>.result-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 0.25rem;
|
||||
|
||||
> .result-header {
|
||||
>.result-header {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 0.25rem 0;
|
||||
align-items: center;
|
||||
|
||||
> .result-name {
|
||||
>.result-name {
|
||||
font-weight: bold;
|
||||
font-size: larger;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
> .result-country {
|
||||
>.result-country {
|
||||
text-transform: uppercase;
|
||||
font-size: small;
|
||||
margin-right: 0.25rem;
|
||||
@ -41,32 +41,43 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .result-details {
|
||||
>.result-details {
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .total-accommodation {
|
||||
>.total-accommodation {
|
||||
margin: 0.5rem 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
|
||||
> mat-icon {
|
||||
>mat-icon {
|
||||
margin-right: 0.5rem;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> .searched-params {
|
||||
>.searched-params {
|
||||
margin: 0.5rem 0
|
||||
}
|
||||
|
||||
.undefined {
|
||||
color: #8f8f8f;
|
||||
}
|
||||
|
||||
.result-desc {
|
||||
text-transform: uppercase;
|
||||
font-size: small;
|
||||
margin-right: 0.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
overflow-y: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +95,7 @@
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
> mat-icon {
|
||||
>mat-icon {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@
|
||||
<mat-vertical-stepper>
|
||||
<!-- Date input -->
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>When is your trip?</ng-template>
|
||||
<ng-template matStepLabel>When do you want to travel?</ng-template>
|
||||
<div class="vertical-wrap">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Start</mat-label>
|
||||
@ -24,7 +24,7 @@
|
||||
</mat-step>
|
||||
<!-- Multi presets -->
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>Which climate would you prefer?</ng-template>
|
||||
<ng-template matStepLabel>Which climate makes you feel comfortable?</ng-template>
|
||||
<div *ngFor="let key of multiPresetsKeys" class="sub-group">
|
||||
<span class="label">{{key|translate}}:</span><br>
|
||||
<mat-radio-group [ngModel]="multiPresetSelection[key]" [value]="undefined">
|
||||
@ -89,14 +89,16 @@
|
||||
</section>
|
||||
<!-- Climate Params -->
|
||||
<section class="group">
|
||||
<span class="title">Climate</span>
|
||||
<app-toggle-slider [(model)]="temperatureMeanMax" [label]="'Max Temp'" [max]="45" [min]="0"></app-toggle-slider>
|
||||
<span class="title small-bottom-margin">Climate</span>
|
||||
<span class="desc">Choose your sweetspot</span>
|
||||
<app-toggle-slider [(model)]="temperatureMeanMax" [label]="'Temperature'" [max]="45" [min]="0"></app-toggle-slider>
|
||||
<app-toggle-slider [(model)]="precipitation" [label]="'Precipitation'" [max]="500"
|
||||
[min]="0"></app-toggle-slider>
|
||||
</section>
|
||||
<!-- Financial -->
|
||||
<section class="group">
|
||||
<span class="title">Fincancial</span>
|
||||
<span class="title small-bottom-margin">Fincancial</span>
|
||||
<span class="desc">Choose your sweetspot</span>
|
||||
<app-toggle-slider [(model)]="accommodation" [label]="'Accommodation'" [max]="60" [min]="0"></app-toggle-slider>
|
||||
</section>
|
||||
</mat-tab>
|
||||
|
||||
@ -83,3 +83,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.small-bottom-margin {
|
||||
margin-bottom: 4px !important;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {Region} from '../../interfaces/region.interface';
|
||||
import {ShareDialogComponent} from '../../dialogs/share-dialog/share-dialog.component';
|
||||
import {MatDialog} from '@angular/material';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Region } from '../../interfaces/region.interface';
|
||||
import { ShareDialogComponent } from '../../dialogs/share-dialog/share-dialog.component';
|
||||
import { MatDialog } from '@angular/material';
|
||||
|
||||
@Component({
|
||||
selector: 'app-share-button',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<div #container *ngIf="region">
|
||||
<img alt="Picture of {{region.name}}" class="region-img"
|
||||
src="https://travopti.de/api/v1/regions/{{region.region_id}}/image">
|
||||
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>
|
||||
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<app-bookmark-button [region]="region"></app-bookmark-button>
|
||||
<a href="https://www.google.com/flights?q=flight+to+{{uriRegionName}}" mat-icon-button matTooltip="Search flights"
|
||||
rel="noopener" target="_blank">
|
||||
rel="noopener" target="_blank">
|
||||
<mat-icon>flight_takeoff</mat-icon>
|
||||
</a>
|
||||
<app-share-button [region]="region"></app-share-button>
|
||||
@ -16,7 +16,7 @@
|
||||
<p *ngIf="region.description" class="region-decsription">
|
||||
<span>{{region.description.substr(0, DESC_CUT_POINT)}}</span>
|
||||
<span (click)="isDescExtended=true" *ngIf="!isDescExtended && region.description.length > DESC_CUT_POINT"
|
||||
class="more-btn"> ...more</span>
|
||||
class="more-btn"> ...more</span>
|
||||
<span *ngIf="isDescExtended">{{region.description.substr(DESC_CUT_POINT)}}</span>
|
||||
</p>
|
||||
<div class="region-stats-group">
|
||||
@ -27,40 +27,27 @@
|
||||
<mat-tab-group>
|
||||
<mat-tab *ngIf="region.avg_price_relative" label="Price Deviation">
|
||||
<ng-template matTabContent>
|
||||
<app-graph
|
||||
[monthlyDatas]="[region.avg_price_relative]"
|
||||
class="graph"
|
||||
formatSting="##,##%"
|
||||
graphType="column">
|
||||
<app-graph [monthlyDatas]="[region.avg_price_relative]" class="graph" formatSting="##,##%" graphType="column">
|
||||
</app-graph>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab *ngIf="region.temperature_mean_max && region.temperature_mean_max[0]" label="Temperatures">
|
||||
<ng-template matTabContent>
|
||||
<app-graph [colors]="['blue', 'red']"
|
||||
[labels]="['Min', 'Max']"
|
||||
[monthlyDatas]="[region.temperature_mean_min, region.temperature_mean_max]"
|
||||
class="graph"
|
||||
formatSting="##,##°C">
|
||||
<app-graph [colors]="['blue', 'red']" [labels]="['Min', 'Max']"
|
||||
[monthlyDatas]="[region.temperature_mean_min, region.temperature_mean_max]" class="graph"
|
||||
formatSting="##,##°C">
|
||||
</app-graph>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab *ngIf="region.precipitation && region.precipitation[0]" label="Precipitation">
|
||||
<ng-template matTabContent>
|
||||
<app-graph
|
||||
[monthlyDatas]="[region.precipitation]"
|
||||
class="graph"
|
||||
formatSting="####mm">
|
||||
<app-graph [monthlyDatas]="[region.precipitation]" class="graph" formatSting="####mm">
|
||||
</app-graph>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab *ngIf="region.rain_days && region.rain_days[0]" label="Rain days">
|
||||
<ng-template matTabContent>
|
||||
<app-graph
|
||||
[monthlyDatas]="[region.rain_days]"
|
||||
class="graph"
|
||||
formatSting="####"
|
||||
graphType="column">
|
||||
<app-graph [monthlyDatas]="[region.rain_days]" class="graph" formatSting="####" graphType="column">
|
||||
</app-graph>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
@ -76,4 +63,4 @@
|
||||
|
||||
<div *ngIf="!region" class="spinner">
|
||||
<mat-spinner></mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
@ -53,8 +53,8 @@ export class SearchComponent implements OnInit {
|
||||
|
||||
this.sortOptions = [
|
||||
{name: 'Relevance', property: 'score', descending: true},
|
||||
{name: 'Name', property: 'name'},
|
||||
{name: 'Accommodation', property: 'accommodation_costs'}
|
||||
{name: 'Region', property: 'name'},
|
||||
{name: 'Accommodation price', property: 'accommodation_costs'}
|
||||
];
|
||||
|
||||
if (this.results.length > 0) {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
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 {Region} from '../interfaces/region.interface';
|
||||
import {Place} from '../interfaces/places.interface';
|
||||
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 { Region } from '../interfaces/region.interface';
|
||||
import { Place } from '../interfaces/places.interface';
|
||||
|
||||
/**
|
||||
* The data service handles all API interactions.
|
||||
@ -27,7 +27,7 @@ export class DataService {
|
||||
public searchRegions(query: string): Promise<Result[]> {
|
||||
const params = new HttpParams().set('q', query);
|
||||
|
||||
return this.http.get<Result[]>(this.API_URL + '/search', {params}).toPromise();
|
||||
return this.http.get<Result[]>(this.API_URL + '/search', { params }).toPromise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,7 +46,7 @@ export class DataService {
|
||||
if (max) {
|
||||
params = params.set('randomize', max.toString(10));
|
||||
}
|
||||
const regions = await this.http.get<Region[]>(this.API_URL + '/regions', {params}).toPromise();
|
||||
const regions = await this.http.get<Region[]>(this.API_URL + '/regions', { params }).toPromise();
|
||||
|
||||
regions.forEach(region => this.regionCache.set(region.region_id, region));
|
||||
|
||||
@ -90,60 +90,144 @@ export class DataService {
|
||||
export const REGION_PARAM_VIS: RegionParamVisLookup = {
|
||||
temperature_mean: {
|
||||
icon: 'wb_sunny',
|
||||
unit: '°C'
|
||||
unit: '°C',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
temperature_mean_min: {
|
||||
icon: 'wb_sunny',
|
||||
unit: '°C'
|
||||
unit: '°C',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
temperature_mean_max: {
|
||||
icon: 'wb_sunny',
|
||||
unit: '°C'
|
||||
unit: '°C',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
precipitation: {
|
||||
icon: 'opacity',
|
||||
unit: 'mm'
|
||||
unit: 'mm',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
humidity: {
|
||||
icon: 'grain',
|
||||
unit: '%'
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
sun_hours: {
|
||||
icon: 'flare',
|
||||
unit: 'h'
|
||||
unit: 'h',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
rain_days: {
|
||||
icon: 'date_range',
|
||||
unit: ''
|
||||
unit: '',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
food_costs: {
|
||||
icon: 'local_dining',
|
||||
unit: '€/day'
|
||||
unit: '€/day',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
alcohol_costs: {
|
||||
icon: 'local_bar',
|
||||
unit: '€/day'
|
||||
unit: '€/day',
|
||||
decimals: '1.2-2'
|
||||
},
|
||||
water_costs: {
|
||||
icon: 'local_cafe',
|
||||
unit: '€/day'
|
||||
unit: '€/day',
|
||||
decimals: '1.2-2'
|
||||
},
|
||||
local_transportation_costs: {
|
||||
icon: 'commute',
|
||||
unit: '€/day'
|
||||
unit: '€/day',
|
||||
decimals: '1.2-2'
|
||||
},
|
||||
entertainment_costs: {
|
||||
icon: 'local_activity',
|
||||
unit: '€/day'
|
||||
unit: '€/day',
|
||||
decimals: '1.2-2'
|
||||
},
|
||||
accommodation_costs: {
|
||||
icon: 'hotel',
|
||||
unit: '€/day'
|
||||
unit: '€/day',
|
||||
decimals: '1.2-2'
|
||||
},
|
||||
average_per_day_costs: {
|
||||
icon: 'euro',
|
||||
unit: '€/day'
|
||||
}
|
||||
unit: '€/day',
|
||||
decimals: '1.2-2'
|
||||
},
|
||||
avg_price_relative: {
|
||||
icon: 'hotel',
|
||||
unit: '%',
|
||||
decimals: '1.1-1'
|
||||
},
|
||||
beach: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
history: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
nature: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
art: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
culture: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
mountains: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
architecture: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
rainforest: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
nightlife: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
desert: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
food: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
shopping: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
volcanoes: {
|
||||
icon: 'stars',
|
||||
unit: '%',
|
||||
decimals: '1.0-0'
|
||||
},
|
||||
};
|
||||
|
||||
export interface RegionParamVisLookup {
|
||||
@ -153,4 +237,5 @@ export interface RegionParamVisLookup {
|
||||
export interface RegionParamVis {
|
||||
icon: string;
|
||||
unit: string;
|
||||
decimals: string;
|
||||
}
|
||||
|
||||
@ -1,33 +1,48 @@
|
||||
{
|
||||
"temperature_mean_max": "Max Temperature Average",
|
||||
"temperature_mean_max": "Day temperature",
|
||||
"temperature": "Temperature",
|
||||
"rain_days": "Rainy days",
|
||||
"sun_hours": "Sunny hours",
|
||||
"rain_days": "Rain days",
|
||||
"sun_hours": "Sunshine",
|
||||
"precipitation": "Precipitation",
|
||||
"humidity": "Humidity",
|
||||
"alcohol_costs": "Alcohol",
|
||||
"food_costs": "Food",
|
||||
"water_costs": "Water",
|
||||
"cheap_alcohol": "Cheap alcohol",
|
||||
"cheap_alcohol": "cheap alcohol",
|
||||
"local_transportation_costs": "Public transport",
|
||||
"average_per_day_costs": "Total costs",
|
||||
"entertainment_costs": "Entertainment",
|
||||
"accommodation_costs": "Accommodation",
|
||||
"cheap_food": "Cheap food",
|
||||
"cheap_water": "Cheap water",
|
||||
"cheap_transportations": "Cheap public transport",
|
||||
"cheap_entertainment": "Cheap entertainment",
|
||||
"cheap_accommodation": "Cheap accommodation",
|
||||
"off_season": "Off-season",
|
||||
"accommodation_costs": "Accommodation price",
|
||||
"avg_price_relative": "Price tendency",
|
||||
"cheap_food": "cheap food",
|
||||
"cheap_water": "cheap water",
|
||||
"cheap_transportations": "cheap public transport",
|
||||
"cheap_entertainment": "cheap entertainment",
|
||||
"cheap_accommodation": "cheap accommodation",
|
||||
"off_season": "low season",
|
||||
"warm": "warm",
|
||||
"chilly": "cold",
|
||||
"mild:": "mild",
|
||||
"cold": "freezing",
|
||||
"sunny": "sunny",
|
||||
"dark": "dark",
|
||||
"almost_no_rain": "almost none",
|
||||
"little_rain": "little",
|
||||
"floodlike_rain": "flooding",
|
||||
"sunny": "all day long",
|
||||
"dark": "the sun scares me",
|
||||
"normal": "better not so much",
|
||||
"almost_no_rain": "no rain",
|
||||
"little_rain": "a little is good",
|
||||
"floodlike_rain": "i like it pouring",
|
||||
"few_raindays": "few",
|
||||
"many_raindays": "many"
|
||||
"many_raindays": "many",
|
||||
"art": "Art",
|
||||
"beach": "Beach",
|
||||
"history": "History",
|
||||
"nature": "Nature",
|
||||
"culture": "Culture",
|
||||
"mountains": "Mountains",
|
||||
"architecture": "Architecture",
|
||||
"rainforest": "Rainforest",
|
||||
"desert": "Desert",
|
||||
"food": "Food",
|
||||
"shopping": "Shopping",
|
||||
"volcanoes": "Volcanoes",
|
||||
"nightlife": "Nightlife"
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user