Add total costs to results
This commit is contained in:
parent
6be202a0d2
commit
44b09a22e8
@ -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>
|
||||
@ -10,14 +10,27 @@
|
||||
<app-share-button [region]="result"></app-share-button>
|
||||
</div>
|
||||
<div class="result-details">
|
||||
<mat-divider *ngIf="result.total_accommodation_costs"></mat-divider>
|
||||
<div *ngIf="result.total_accommodation_costs" class="total-accommodation">
|
||||
<mat-icon>euro</mat-icon>
|
||||
<span matTooltip="Total accommodation">{{result.total_accommodation_costs|number:'1.2-2'}}€</span>
|
||||
<mat-divider *ngIf="totalCosts"></mat-divider>
|
||||
<div *ngIf="totalCosts" class="total-price-container">
|
||||
<div matTooltip="Total">
|
||||
<mat-icon>euro</mat-icon>
|
||||
<span>{{totalCosts|number:'1.0-0'}}€</span>
|
||||
</div>
|
||||
<div matTooltip="Accommodation">
|
||||
<mat-icon>hotel</mat-icon>
|
||||
<span>{{totalAccommodation|number:'1.0-0'}}€</span>
|
||||
</div>
|
||||
<div matTooltip="Lifestyle">
|
||||
<mat-icon>people</mat-icon>
|
||||
<span>{{totalLifeStyle|number:'1.0-0'}}€</span>
|
||||
</div>
|
||||
<div (click)="onTravelCostRequest($event)" matTooltip="Travel (request)">
|
||||
<mat-icon>commute</mat-icon>
|
||||
<span>- - -</span>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider *ngIf="result.scores.length > 0"></mat-divider>
|
||||
<div *ngIf="result.scores.length > 0" class="searched-params">
|
||||
|
||||
<table>
|
||||
<tr *ngFor="let score of result.scores" [ngClass]="{'undefined': score.value == undefined}">
|
||||
<td>
|
||||
@ -45,6 +58,6 @@
|
||||
</table>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="result-desc">Estimated values for your chosen travel dates</div>
|
||||
<div class="result-desc">Estimated values for {{duration}} {{duration > 1 ? 'days' : 'day'}}</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,26 +41,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
>.result-details {
|
||||
> .result-details {
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
>.total-accommodation {
|
||||
margin: 0.5rem 0;
|
||||
> .total-price-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
margin: 0.5rem 0;
|
||||
|
||||
>mat-icon {
|
||||
margin-right: 0.5rem;
|
||||
margin-left: 3px;
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 1rem;
|
||||
|
||||
> mat-icon {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
>.searched-params {
|
||||
> .searched-params {
|
||||
margin: 0.5rem 0
|
||||
}
|
||||
|
||||
@ -96,7 +99,7 @@
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
>mat-icon {
|
||||
> mat-icon {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
|
||||
import {Result} from '../../interfaces/result.interface';
|
||||
import {REGION_PARAM_VIS} from '../../services/data.service';
|
||||
|
||||
@ -7,14 +7,23 @@ import {REGION_PARAM_VIS} from '../../services/data.service';
|
||||
templateUrl: './result.component.html',
|
||||
styleUrls: ['./result.component.scss']
|
||||
})
|
||||
export class ResultComponent implements OnInit {
|
||||
export class ResultComponent implements OnInit, OnChanges {
|
||||
|
||||
@Input()
|
||||
result: Result;
|
||||
|
||||
/** Date difference in days */
|
||||
@Input()
|
||||
duration: number;
|
||||
|
||||
@Input()
|
||||
debug = false;
|
||||
|
||||
totalCosts: number;
|
||||
totalAccommodation: number;
|
||||
totalLifeStyle: number;
|
||||
totalTravel: number;
|
||||
|
||||
/** Contains the visual definitions */
|
||||
readonly PROPERTY_VIS_DEF = REGION_PARAM_VIS;
|
||||
|
||||
@ -24,4 +33,25 @@ export class ResultComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.result || changes.duration) {
|
||||
this.calculateTotalPrices();
|
||||
}
|
||||
}
|
||||
|
||||
onTravelCostRequest(event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
window.open(`https://www.google.com/flights?q=flight+to+${encodeURI(this.result.name)}`, '_blank');
|
||||
}
|
||||
|
||||
private calculateTotalPrices() {
|
||||
// Guard: undefined values
|
||||
if (!this.result || !this.duration) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.totalCosts = Math.round(this.result.average_per_day_costs * this.duration);
|
||||
this.totalAccommodation = Math.round(this.result.accommodation_costs * this.duration);
|
||||
this.totalLifeStyle = this.totalCosts - this.totalAccommodation;
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="result-container">
|
||||
<app-result (click)="onResultClick(result)" *ngFor="let result of results" [debug]="debug"
|
||||
[result]="result"></app-result>
|
||||
[duration]="duration" [result]="result"></app-result>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@ import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {Result} from '../../interfaces/result.interface';
|
||||
import {SearchService} from '../../services/search.service';
|
||||
import {base64ToObj} from '../../utils/base64conversion';
|
||||
import {Query} from '../../interfaces/search-request.interface';
|
||||
|
||||
interface SortOption {
|
||||
name: string;
|
||||
@ -28,6 +30,8 @@ export class SearchComponent implements OnInit {
|
||||
sortDes = true;
|
||||
/** Available sort options */
|
||||
sortOptions: SortOption[] = [];
|
||||
/** The difference between from and to in days */
|
||||
duration: number;
|
||||
|
||||
debug = false;
|
||||
|
||||
@ -54,7 +58,7 @@ export class SearchComponent implements OnInit {
|
||||
this.sortOptions = [
|
||||
{name: 'Relevance', property: 'score', descending: true},
|
||||
{name: 'Region name', property: 'name'},
|
||||
{name: 'Accommodation price', property: 'accommodation_costs'}
|
||||
{name: 'Price', property: 'average_per_day_costs'}
|
||||
];
|
||||
|
||||
if (this.results.length > 0) {
|
||||
@ -65,6 +69,10 @@ export class SearchComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate duration
|
||||
const {from, to} = base64ToObj(this.queryString) as Query;
|
||||
const difference: number = (new Date(to)).getTime() - (new Date(from)).getTime();
|
||||
this.duration = Math.round(difference / 1000 / 60 / 60 / 24);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user