-
- {{bike.name}}
+
+
+ {{bike.name}}
+
+
+
+
+
+
{{bike.batteryPercentage + " %"}}
+
+
+
{{bike.distance + " km"}}
+
{{bike.address+" "+bike.HouseNumber+ ", " +bike.PostalCode}}
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+ Bike Name
+
+
+ {{selectedBike.name}}
+
+
+
+
+ Battery Level
+
+
+
+
+ {{selectedBike.batteryPercentage + " %"}}
+
+
+
+
+ Bike Location
+
+
+ {{selectedBike.address}}
+
+
+
+
+ Bike Distance
+
+
+ {{selectedBike.distance + " km"}}
+
+
+
+
+ Reserve
+
+
+ Navigate
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/home/home.page.scss b/src/app/home/home.page.scss
index ad23a37ddafdd5afa5f7986772357fb31cf50969..3762aeac0023826c387752b91cd3198788750df1 100644
--- a/src/app/home/home.page.scss
+++ b/src/app/home/home.page.scss
@@ -99,4 +99,8 @@ ion-footer{
.get-position{
margin-bottom:10px;
+}
+
+.button-container{
+ clear: both;
}
\ No newline at end of file
diff --git a/src/app/home/home.page.ts b/src/app/home/home.page.ts
index 4d5018b303ae87f49aa9b52f2d5098c895a6ebbe..21af6c44bdd7780fa5a8b8026627bc844968fe7e 100644
--- a/src/app/home/home.page.ts
+++ b/src/app/home/home.page.ts
@@ -4,6 +4,7 @@ import { RestService } from '../rest.service';
import { Observable } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Storage } from '@ionic/storage';
+import { ToastService } from '../services/toast.service';
declare var H: any;
@@ -25,6 +26,9 @@ export class HomePage {
private currentLocation = { lat: 0, lng: 0 };
public is3DChecked = false;
+ public isDetailsVisible = false;
+ public selectedBike ={id: 0};
+ public isBikeReserved= false;
public tempArr = [1, 2];
public locationArr = [{ lat: 48.778409, lng: 9.179252 },
@@ -44,7 +48,8 @@ export class HomePage {
constructor(private geolocation: Geolocation,
public restService: RestService,
public httpClient: HttpClient,
- private storage: Storage) {
+ private storage: Storage,
+ private toastService: ToastService) {
this.platform = new H.service.Platform({
'apikey': 'tiVTgBnPbgV1spie5U2MSy-obhD9r2sGiOCbBzFY2_k'
@@ -58,14 +63,14 @@ export class HomePage {
ngAfterViewInit() {
setTimeout(() => {
this.loadmap("2D");
- }, 200);
+ }, 700);
window.addEventListener('resize', () => this.map.getViewPort().resize());
}
getBikesList() {
this.geolocation.getCurrentPosition({
- maximumAge: 1000, timeout: 1000,
+ maximumAge: 1000, timeout: 4000,
enableHighAccuracy: true
}).then((resp) => {
this.currentLocation.lat = resp.coords.latitude;
@@ -95,10 +100,6 @@ export class HomePage {
});
}
-
-
-
-
loadmap(style) {
// Obtain the default map types from the platform object
var mapStyle = "raster";
@@ -231,6 +232,7 @@ export class HomePage {
}, 100);
}
+
reverseGeocode(platform, lat, lng, index) {
var prox = lat + ',' + lng + ',56';
var geocoder = platform.getGeocodingService(),
@@ -257,11 +259,31 @@ export class HomePage {
}
+ showBikeDetails(bike) {
+ this.selectedBike=bike;
+ this.selectedBike.id=bike.id;
+ this.isDetailsVisible = true;
+ }
+ reserveBike() {
+ //this.selectedBike=bikeS;
+ this.storage.get('token').then((token) => {
+ let url = 'http://193.196.52.237:8081/reservation' + '?bikeId=' + this.selectedBike.id;
+ const headers = new HttpHeaders().set("Authorization", "Bearer " + token);
+ this.bikeApi = this.httpClient.get(url, { headers });
+ this.bikeApi.subscribe((resp) => {
+ console.log('my data: ', resp);
+ this.isBikeReserved=true;
+ this.toastService.showToast("Reservation Successful!");
+ }, (error) => {
+ console.log(error)
+ this.toastService.showToast("Only one bike may be reserved or rented at a time")
+ });
+ });
+
-
-
-
-
+ }
+
+
}
diff --git a/src/app/myreservation/myreservation-routing.module.ts b/src/app/myreservation/myreservation-routing.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b5fb9f3d98d059c35db1c5b723adaf1624cb68c
--- /dev/null
+++ b/src/app/myreservation/myreservation-routing.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { MyreservationPage } from './myreservation.page';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: MyreservationPage
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class MyreservationPageRoutingModule {}
diff --git a/src/app/myreservation/myreservation.module.ts b/src/app/myreservation/myreservation.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aaf6b5af89541878e353d848a843c1777367ee8e
--- /dev/null
+++ b/src/app/myreservation/myreservation.module.ts
@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { MyreservationPageRoutingModule } from './myreservation-routing.module';
+
+import { MyreservationPage } from './myreservation.page';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ IonicModule,
+ MyreservationPageRoutingModule
+ ],
+ declarations: [MyreservationPage]
+})
+export class MyreservationPageModule {}
diff --git a/src/app/myreservation/myreservation.page.html b/src/app/myreservation/myreservation.page.html
new file mode 100644
index 0000000000000000000000000000000000000000..76a54fc513bcac7766a7718eaa9a00f1121d6f5d
--- /dev/null
+++ b/src/app/myreservation/myreservation.page.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+ My Reservation
+
+
+
+
+
+
+
+ No reservation found
+
+
+
+
+
+
+
+
+
+
+
+ Bike Name
+ {{bikeDetails.name}}
+
+
+ Battery Level
+
+
+ {{bikeDetails.batteryPercentage +" %"}}
+
+
+
+ Bike Location
+ {{bikeDetails.address}}
+
+
+ Bike Distance
+ {{ bikeDetails.distance +" m"}}
+
+
+
+ Hire
+
+
+ Cancel Reservation
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/myreservation/myreservation.page.scss b/src/app/myreservation/myreservation.page.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/myreservation/myreservation.page.spec.ts b/src/app/myreservation/myreservation.page.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..13da4644692cf67e8de0ecd4522e7eda36438b82
--- /dev/null
+++ b/src/app/myreservation/myreservation.page.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { IonicModule } from '@ionic/angular';
+
+import { MyreservationPage } from './myreservation.page';
+
+describe('MyreservationPage', () => {
+ let component: MyreservationPage;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ MyreservationPage ],
+ imports: [IonicModule.forRoot()]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(MyreservationPage);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ }));
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/myreservation/myreservation.page.ts b/src/app/myreservation/myreservation.page.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3d7617b769c922e6ccf6133fd750bc650c8efbe9
--- /dev/null
+++ b/src/app/myreservation/myreservation.page.ts
@@ -0,0 +1,266 @@
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+
+import { Geolocation } from '@ionic-native/geolocation/ngx';
+import { RestService } from '../rest.service';
+import { Observable } from 'rxjs';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Storage } from '@ionic/storage';
+import { ToastService } from '../services/toast.service';
+import { Router } from '@angular/router';
+
+declare var H: any;
+
+@Component({
+ selector: 'app-myreservation',
+ templateUrl: './myreservation.page.html',
+ styleUrls: ['./myreservation.page.scss'],
+})
+export class MyreservationPage implements OnInit {
+ private platform: any;
+ private map: any;
+ // Get an instance of the routing service:
+ private mapRouter: any;
+
+ reservedBike: any = {};
+ bikeDetails: any = {};
+
+ noReservation = true;
+
+ private currentLocation = { lat: 0, lng: 0 };
+
+ // Create the parameters for the routing request:
+ private routingParameters = {
+ // The routing mode:
+ mode: 'shortest;pedestrian',
+ // The start point of the route:
+ waypoint0: 'geo!50.1120423728813,8.68340740740811',
+ // The end point of the route:
+ waypoint1: 'geo!52.5309916298853,13.3846220493377',
+ // To retrieve the shape of the route we choose the route
+ // representation mode 'display'
+ representation: 'display'
+ };
+
+ @ViewChild("mapElement", { static: false })
+ public mapElement: ElementRef;
+
+ constructor(private geolocation: Geolocation,
+ public restService: RestService,
+ public httpClient: HttpClient,
+ private storage: Storage,
+ private toastService: ToastService,
+ private router: Router) {
+ this.platform = new H.service.Platform({
+ 'apikey': 'tiVTgBnPbgV1spie5U2MSy-obhD9r2sGiOCbBzFY2_k'
+ });
+ this.mapRouter = this.platform.getRoutingService();
+ }
+
+ ngOnInit() {
+ this.getReservedBike();
+ }
+
+ ngAfterViewInit() {
+
+ }
+
+ getReservedBike() {
+ this.storage.get('token').then((token) => {
+ const headers = new HttpHeaders().set("Authorization", "Bearer " + token);
+ //call reserved bike api
+ let reserveUrl = 'http://193.196.52.237:8081/active-rent';
+ let bikeReservationStatusApi = this.httpClient.get(reserveUrl, { headers });
+ bikeReservationStatusApi.subscribe((resp: any) => {
+ console.log('Reserved Bike', resp);
+ if (resp.data) {
+ this.reservedBike = resp.data;
+ //Call Bike Details api
+ let bikeDetailsUrl = 'http://193.196.52.237:8081/bikes/' + this.reservedBike.bikeId;
+ let bikeDetailsApi = this.httpClient.get(bikeDetailsUrl, { headers });
+ bikeDetailsApi.subscribe((resp: any) => {
+ console.log('Bike Details', resp);
+ this.bikeDetails = resp.data;
+ this.noReservation = false;
+
+ // display map
+ setTimeout(() => {
+ this.loadmap();
+ }, 1000);
+ window.addEventListener('resize', () => this.map.getViewPort().resize());
+ }, (reservedBikeError) => console.log(reservedBikeError));
+ }
+ }, (bikeDetailsError) => console.log(bikeDetailsError));
+ });
+ }
+
+ cancelReservation() {
+ this.storage.get('token').then((token) => {
+ let url = 'http://193.196.52.237:8081/reservation' + '?bikeId=' + this.bikeDetails.id;
+ const headers = new HttpHeaders().set("Authorization", "Bearer " + token);
+ let bikeApi = this.httpClient.delete(url, { headers });
+ bikeApi.subscribe((resp) => {
+ console.log('Reservation Cancelled: ', resp);
+ this.toastService.showToast("Bike Reservation successfully cancelled.");
+ this.router.navigateByUrl('/home');
+ }, (error) => console.log(error));
+ });
+ }
+
+ loadmap() {
+ var defaultLayers = this.platform.createDefaultLayers();
+ this.map = new H.Map(
+ this.mapElement.nativeElement,
+ defaultLayers.raster.normal.map,
+ {
+ zoom: 17,
+ pixelRatio: window.devicePixelRatio || 1
+ }
+ );
+
+ var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(this.map));
+ var ui = H.ui.UI.createDefault(this.map, defaultLayers);
+ ui.removeControl("mapsettings");
+ // create custom one
+ var ms = new H.ui.MapSettingsControl({
+ baseLayers: [{
+ label: "3D", layer: defaultLayers.vector.normal.map
+ }, {
+ label: "Normal", layer: defaultLayers.raster.normal.map
+ }, {
+ label: "Satellite", layer: defaultLayers.raster.satellite.map
+ }, {
+ label: "Terrain", layer: defaultLayers.raster.terrain.map
+ }
+ ],
+ layers: [{
+ label: "layer.traffic", layer: defaultLayers.vector.normal.traffic
+ },
+ {
+ label: "layer.incidents", layer: defaultLayers.vector.normal.trafficincidents
+ }
+ ]
+ });
+ ui.addControl("customized", ms);
+ var mapSettings = ui.getControl('customized');
+ var zoom = ui.getControl('zoom');
+ mapSettings.setAlignment('top-right');
+ zoom.setAlignment('left-top');
+
+ //get user location
+ this.getLocation(this.map);
+
+ var img = ['../../../assets/images/100_percent.png', '../../../assets/images/75_percent.png', '../../../assets/images/50_percent.png', '../../../assets/images/25_percent.png', '../../../assets/images/0_percent.png'];
+ if (this.bikeDetails.batteryPercentage < 100 && this.bikeDetails.batteryPercentage >= 75) {
+ this.addMarker(Number(this.bikeDetails.lat), Number(this.bikeDetails.lon), img[0]);
+ }
+ else if (this.bikeDetails.batteryPercentage < 75 && this.bikeDetails.batteryPercentage >= 50) {
+ this.addMarker(Number(this.bikeDetails.lat), Number(this.bikeDetails.lon), img[1]);
+ }
+ else if (this.bikeDetails.batteryPercentage < 50 && this.bikeDetails.batteryPercentage >= 25) {
+ this.addMarker(Number(this.bikeDetails.lat), Number(this.bikeDetails.lon), img[2]);
+ } else if (this.bikeDetails.batteryPercentage < 25 && this.bikeDetails.batteryPercentage >= 0) {
+ this.addMarker(Number(this.bikeDetails.lat), Number(this.bikeDetails.lon), img[3]);
+ }
+ }
+
+ getLocation(map) {
+ this.geolocation.getCurrentPosition(
+ {
+ maximumAge: 1000, timeout: 5000,
+ enableHighAccuracy: true
+ }
+ ).then((resp) => {
+ let lat = resp.coords.latitude
+ let lng = resp.coords.longitude
+ this.currentLocation.lat = resp.coords.latitude;
+ this.currentLocation.lng = resp.coords.longitude;
+ this.moveMapToGiven(map, lat, lng);
+ // set routing params
+ this.routingParameters.waypoint1 = 'geo!' + this.bikeDetails.lat + ',' + this.bikeDetails.lon;
+ this.routingParameters.waypoint0 = 'geo!' + this.currentLocation.lat + ',' + this.currentLocation.lng;
+
+ // show route on map
+ this.mapRouter.calculateRoute(this.routingParameters, this.onResult.bind(this),
+ (error) => {
+ alert(error.message);
+ });
+ }, er => {
+ alert('Can not retrieve Location')
+ }).catch((error) => {
+ alert('Error getting location - ' + JSON.stringify(error))
+ });
+ }
+
+ moveMapToGiven(map, lat, lng) {
+ var icon = new H.map.Icon('../../../assets/images/current_location.png');
+ // Create a marker using the previously instantiated icon:
+ var marker = new H.map.Marker({ lat: lat, lng: lng }, { icon: icon });
+ // Add the marker to the map:
+ map.addObject(marker);
+ map.setCenter({ lat: lat, lng: lng });
+ }
+
+ addMarker(lat, lng, img) {
+ var icon = new H.map.Icon(img);
+ // Create a marker using the previously instantiated icon:
+ var marker = new H.map.Marker({ lat: lat, lng: lng }, { icon: icon });
+ // Add the marker to the map:
+ this.map.addObject(marker);
+ }
+
+
+ // Define a callback function to process the routing response:
+ onResult(result) {
+ var route,
+ routeShape,
+ startPoint,
+ endPoint,
+ linestring;
+ if (result.response.route) {
+ // Pick the first route from the response:
+ route = result.response.route[0];
+ // Pick the route's shape:
+ routeShape = route.shape;
+
+ // Create a linestring to use as a point source for the route line
+ linestring = new H.geo.LineString();
+
+ // Push all the points in the shape into the linestring:
+ routeShape.forEach(function (point) {
+ var parts = point.split(',');
+ linestring.pushLatLngAlt(parts[0], parts[1]);
+ });
+
+ // Retrieve the mapped positions of the requested waypoints:
+ startPoint = route.waypoint[0].mappedPosition;
+ endPoint = route.waypoint[1].mappedPosition;
+
+ // Create a polyline to display the route:
+ var routeLine = new H.map.Polyline(linestring, {
+ /* style: {
+ lineWidth: 10,
+ fillColor: 'white',
+ strokeColor: 'rgba(255, 255, 255, 1)',
+ lineDash: [0, 2],
+ lineTailCap: 'arrow-tail',
+ lineHeadCap: 'arrow-head'
+ } */
+ style: {
+ lineWidth: 6,
+ strokeColor: 'rgba(0, 72, 255, 0.8)',
+ lineDash: [0, 2]
+ }
+ });
+
+ // Add the route polyline and the two markers to the map:
+ this.map.addObjects([routeLine]);
+
+ // Set the map's viewport to make the whole route visible:
+ this.map.getViewModel().setLookAtData({ bounds: routeLine.getBoundingBox() });
+ //this.map.setZoom(this.map.getZoom() - 4.3, true);
+ }
+ };
+ hireBike() {
+ this.router.navigateByUrl('/hirebike');
+ }
+}
diff --git a/src/app/rest.service.ts b/src/app/rest.service.ts
index d0156233b399fbc65a643732c5c365fcde495c5f..aadef85b5a4c06e3635e219c7364e490cfc624de 100644
--- a/src/app/rest.service.ts
+++ b/src/app/rest.service.ts
@@ -6,11 +6,14 @@ import { Storage } from '@ionic/storage';
})
export class RestService {
+ public isUserLoggedIn = false;
+ public isLoginPage = false;
+
constructor(private storage: Storage) { }
setToken(token) {
- // set a key/value
this.storage.set('token', token);
+ this.isUserLoggedIn = true;
}
getToken() {
diff --git a/src/app/services/toast.service.spec.ts b/src/app/services/toast.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2dc86ddfe0e0d86894155ddd7aabf2e8f5a46378
--- /dev/null
+++ b/src/app/services/toast.service.spec.ts
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ToastService } from './toast.service';
+
+describe('ToastService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: ToastService = TestBed.get(ToastService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/services/toast.service.ts b/src/app/services/toast.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e892ad39c5c205b82f37b7c796395ae34f98e0ab
--- /dev/null
+++ b/src/app/services/toast.service.ts
@@ -0,0 +1,24 @@
+import { Injectable } from '@angular/core';
+import { ToastController } from '@ionic/angular';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ToastService {
+
+ toast: any;
+
+ constructor(public toastController: ToastController) { }
+
+ showToast(message) {
+ this.toast = this.toastController.create({
+ message: message,
+ duration: 2000
+ }).then((toastData)=>{
+ toastData.present();
+ });
+ }
+ HideToast(){
+ this.toast = this.toastController.dismiss();
+ }
+}
diff --git a/src/assets/images/bike2gologo.png b/src/assets/images/bike2gologo.png
index 03ef687e2a677670be246f79533c0bd0b1e80b50..91d91c1610162aa0a6f5664783ef8ba061510da4 100644
Binary files a/src/assets/images/bike2gologo.png and b/src/assets/images/bike2gologo.png differ