src/app/pages/photographer-search-page/photographer-search-page.component.ts
Photographer search page component
selector | app-photographer-search-page |
styleUrls | photographer-search-page.component.scss |
templateUrl | ./photographer-search-page.component.html |
Properties |
|
Methods |
constructor(geolocation: GeolocationService, afs: FirebaseFirestoreService, service: AlertService)
|
||||||||||||||||
Constructor
Parameters :
|
addPhotographerInCircle | ||||||||
addPhotographerInCircle(circle: number)
|
||||||||
Parameters :
Returns :
void
|
getPhotographerDistance | ||||||||
getPhotographerDistance(photographer: PhotographerProfile)
|
||||||||
return number of kilometres between a certain photographer and the user position
Parameters :
Returns :
number
|
handleEnteredZip | ||||||||
handleEnteredZip(zip: string)
|
||||||||
get entered zip, convert zip to coordinates, refresh map
Parameters :
Returns :
void
|
ngOnInit |
ngOnInit()
|
Initialize component
Returns :
void
|
onKey | ||||||||
onKey(event: any)
|
||||||||
return input value
Parameters :
Returns :
void
|
refreshPhotographerList |
refreshPhotographerList()
|
add photographers to displayed list when they are in the users area
Returns :
void
|
setPosition |
setPosition(latitude: number, longitude: number)
|
Set the position on the map
Returns :
void
|
sortPhotographerByDistance |
sortPhotographerByDistance()
|
Returns :
void
|
Public agmMap |
agmMap:
|
Type : AgmMap
|
Decorators : ViewChild
|
Google maps ref |
Public editedPhotographer |
editedPhotographer:
|
Type : PhotographerProfile[]
|
Default value : []
|
Edited photographer profiles collection |
Public hasBothProfiles |
hasBothProfiles:
|
Type : boolean
|
indicator for parting line |
Private log |
log:
|
Default value : Log.create('PhotographerSearchPageComponent')
|
Logger |
Public photograph |
photograph:
|
Type : PhotographerProfile
|
Default value : {
about: '',
email: '',
facebook: '',
instagram: '',
name: '',
phone: '',
tumbler: '',
twitter: '',
uid: '',
website: '',
premium: false,
profileUrl: '',
location: {
lat: 0,
lng: 0
}
}
|
Photographer profile |
Public photographer |
photographer:
|
Type : PhotographerProfile[]
|
Default value : []
|
Photographer profiles collection |
Private userLat |
userLat:
|
Type : number
|
Users Latitutde |
Private userLng |
userLng:
|
Type : number
|
Users Longitude |
import { AgmMap } from '@agm/core';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Log } from 'ng2-logger';
import { Alert } from '../../interfaces/alert';
import { PhotographerProfile } from '../../interfaces/photographer-profile';
import { AlertService } from '../../services/alert/alert.service';
import { FirebaseFirestoreService } from '../../services/firebase/firestore/firebase-firestore.service';
import { GeolocationService } from '../../services/geolocation/geolocation.service';
/**
* Photographer search page component
* @author Daniel Sogl, Tim Krießler
*/
@Component({
selector: 'app-photographer-search-page',
templateUrl: './photographer-search-page.component.html',
styleUrls: ['./photographer-search-page.component.scss']
})
export class PhotographerSearchPageComponent implements OnInit {
/** Logger */
private log = Log.create('PhotographerSearchPageComponent');
/** Photographer profiles collection */
public photographer: PhotographerProfile[] = [];
/** Edited photographer profiles collection */
public editedPhotographer: PhotographerProfile[] = [];
/** indicator for parting line */
public hasBothProfiles: boolean;
/** Photographer profile */
public photograph: PhotographerProfile = {
about: '',
email: '',
facebook: '',
instagram: '',
name: '',
phone: '',
tumbler: '',
twitter: '',
uid: '',
website: '',
premium: false,
profileUrl: '',
location: {
lat: 0,
lng: 0
}
};
/** Users Latitutde */
private userLat: number;
/** Users Longitude */
private userLng: number;
/** Google maps ref */
@ViewChild('map') public agmMap: AgmMap;
/**
* Constructor
* @param {GeolocationService} geolocation Geolocation Service
* @param {FirebaseFirestoreService} afs Firebase Firestore Service
*/
constructor(
private geolocation: GeolocationService,
private afs: FirebaseFirestoreService,
private service: AlertService
) {}
/**
* Initialize component
*/
ngOnInit() {
this.log.color = 'orange';
this.log.d('Component initialized');
// Init map
this.agmMap.latitude = 51.165691;
this.agmMap.longitude = 10.451526000000058;
this.agmMap.zoom = 11;
// Load all photographer profiles
this.afs
.getAllPhotographer()
.valueChanges()
.subscribe(photographer => {
this.photographer = photographer;
// Get browser geolocation
if (!!navigator.geolocation) {
/* geolocation is available */
this.geolocation
.getBrowserLocation()
.then(position => {
this.log.d('Current position', position.coords);
this.setPosition(
position.coords.latitude,
position.coords.longitude
);
this.userLat = position.coords.latitude;
this.userLng = position.coords.longitude;
// Show photographer profiles of users area
this.refreshPhotographerList();
})
.catch((err: any) => {
this.log.er('Error getting location', err);
});
}
});
}
/**
* return number of kilometres between a certain photographer and the user position
* @param {PhotographerProfile} photographer Photographer profile
* @returns {number}
*/
getPhotographerDistance(photographer: PhotographerProfile): number {
return this.geolocation.calculateGpsDistance(
photographer.location.lat,
photographer.location.lng,
this.userLat,
this.userLng
);
}
/**
* Set the position on the map
* @param {number} latitude Latitude
* @param {number} longitude Longitude
*/
setPosition(latitude: number, longitude: number) {
this.agmMap.latitude = latitude;
this.agmMap.longitude = longitude;
this.agmMap.zoom = 11;
this.agmMap.triggerResize();
}
/**
* return input value
* @param {any} eventm Event
*/
onKey(event: any) {
if (+event.target.value && event.target.value.length === 5) {
this.handleEnteredZip(event.target.value);
} else if (event.target.value.length === 5) {
const alert: Alert = {
title: 'Ungültige PLZ eingegeben!'
};
this.service.showError(alert);
}
}
/**
* get entered zip, convert zip to coordinates, refresh map
* @param {string} zip ZIP
*/
handleEnteredZip(zip: string) {
this.log.info('valid zip-length entered');
this.geolocation.getCoordinatesFromZip(zip).then((result: any) => {
if (result.results[0].geometry.location) {
this.photograph.location = result.results[0].geometry.location;
this.setPosition(
this.photograph.location.lat,
this.photograph.location.lng
);
this.userLat = this.photograph.location.lat;
this.userLng = this.photograph.location.lng;
this.refreshPhotographerList();
} else {
this.log.error('Cannot get location from Service');
}
});
}
/**
* add photographers to displayed list when they are in the users area
*/
refreshPhotographerList() {
// clean displayed list
if (this.editedPhotographer) {
this.editedPhotographer.splice(0);
}
// add photographers in the circle of 10 kilometres
this.addPhotographerInCircle(10);
this.agmMap.zoom = 11;
/** if there are no photographers in the circle of 10 kilometres,
* add photographers in the circle of 25 kilometres
*/
if (!this.editedPhotographer.length) {
const alert: Alert = {
title: 'Kein Fotograf gefunden. Umkreis auf 25km erhöht'
};
this.service.showInfo(alert);
this.addPhotographerInCircle(25);
this.agmMap.zoom = 10;
}
}
addPhotographerInCircle(circle: number) {
let hasPremium: boolean;
let hasStandard: boolean;
hasPremium = false;
hasStandard = false;
this.hasBothProfiles = false;
for (let i = 0; i < this.photographer.length; i++) {
let distance: number;
distance = this.getPhotographerDistance(this.photographer[i]);
// add all photographers in the circle
if (distance <= circle) {
this.editedPhotographer.push(this.photographer[i]);
/** check whether parting line is required */
if (this.photographer[i].premium) {
hasPremium = true;
} else if (!this.photographer[i].premium) {
hasStandard = true;
}
}
if (i === this.photographer.length - 1) {
this.sortPhotographerByDistance();
}
}
if (hasPremium && hasStandard) {
this.hasBothProfiles = true;
}
}
sortPhotographerByDistance() {
if (this.editedPhotographer.length > 0) {
this.editedPhotographer.sort((a, b) => {
if (this.getPhotographerDistance(a) < this.getPhotographerDistance(b)) {
return -1;
}
if (this.getPhotographerDistance(a) > this.getPhotographerDistance(b)) {
return 1;
}
return 0;
});
}
}
}
<div class="container-fluid">
<div class="row mt-5 pt-5">
<div class="col col-lg-4 text-center">
<div class="md-form">
<input mdbActive type="text" class="form-control" (keyup)="onKey($event)">
<label class="active">{{ 'TEXTS.SEARCH_PHOTOGRAPHER' | translate }}</label>
</div>
<div class="scrollable">
<div *ngIf="editedPhotographer.length; else noPhotographer">
<div *ngFor="let p of editedPhotographer">
<div *ngIf="p.premium == true">
<a [routerLink]="['/photographer', p.profileUrl]">
<div class="card">
<div class="card-body">
<p class="name">{{ p.name }}</p>
<div class="content">
<img class="profile-img" [src]="p.photoUrl">
<div *ngIf="p.address" class="address">{{p.address.street}} {{p.address.streetnumber}}
<br/> {{p.address.zip}} {{p.address.city}}
<br/>
</div>
</div>
<br/>
<div class="distance">
{{getPhotographerDistance(p) | number:'0.2-2' | replace:'.':','}} km
</div>
</div>
</div>
</a>
</div>
</div>
<hr *ngIf="hasBothProfiles" class="mt-4 mb-4 border">
<div *ngFor="let p of editedPhotographer">
<div *ngIf="!p.premium">
<a [routerLink]="['/photographer', p.profileUrl]">
<div class="card">
<div class="card-body">
<p class="name">{{ p.name }}</p>
<div>
<div *ngIf="p.address" class="address">{{p.address.street}} {{p.address.streetnumber}}
<br/> {{p.address.zip}} {{p.address.city}}
<br/>
</div>
</div>
<br/>
<div class="distance">
{{getPhotographerDistance(p) | number:'0.2-2' | replace:'.':','}} km
</div>
</div>
</div>
</a>
</div>
</div>
</div>
<ng-template #noPhotographer>
<p>{{ 'TEXTS.NO_PHOTOGRAPHERS_FOUND' | translate}}</p>
</ng-template>
</div>
</div>
<div class="col col-lg-8 text-center">
<agm-map #map class="card mapformat">
<agm-marker *ngFor="let p of editedPhotographer; let i = index" [latitude]="p.location.lat" [longitude]="p.location.lng"
[title]="p.name" [zIndex]="i">
<agm-snazzy-info-window [maxWidth]="300" [closeWhenOthersOpen]="true" [maxHeight]="300">
<ng-template>
<div>
<span class="name">
<b>{{ p.name }}</b>
</span>
<div class="content">
<div>
<img *ngIf="p.premium" class="content-img" [src]="p.photoUrl">
<br/>
</div>
<span *ngIf="p.address.street">{{ p.address.street }} {{p.address.streetnumber}}
<br> {{ p.address.zip }} {{ p.address.city }}</span>
<br>
<span *ngIf="p.phone">Tel: {{ p.phone }}</span>
<br>
</div>
<a [routerLink]="['/photographer', p.profileUrl]">Profile</a>
</div>
</ng-template>
</agm-snazzy-info-window>
</agm-marker>
</agm-map>
</div>
</div>
</div>