diff --git a/resources/android/xml/network_security_config.xml b/resources/android/xml/network_security_config.xml index de61259aac8f4a9c2ddceb7972529ad2490f60f7..15d14099b80b18a5fad8dbe1059e286cd8edb8be 100644 --- a/resources/android/xml/network_security_config.xml +++ b/resources/android/xml/network_security_config.xml @@ -1,6 +1,6 @@ - localhost + 193.196.52.237 - + \ No newline at end of file diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index c85d5d200ce231e3518a953ca235cbbac5053896..485a1d4f12f77e8f3bb8226b9ee9bdafcecadfde 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -18,11 +18,21 @@ const routes: Routes = [ { path: 'login', loadChildren: () => import('./auth/login/login.module').then( m => m.LoginPageModule) + }, + { + path: 'register', + loadChildren: () => import('./auth/register/register.module').then( m => m.RegisterPageModule) }, { - path: 'register', - loadChildren: () => import('./auth/register/register.module').then( m => m.RegisterPageModule) + path: 'myreservation', + loadChildren: () => import('./myreservation/myreservation.module').then( m => m.MyreservationPageModule) + }, + { + path: 'hirebike', + loadChildren: () => import('./hirebike/hirebike.module').then( m => m.HirebikePageModule) } + + ]; @NgModule({ diff --git a/src/app/app.component.html b/src/app/app.component.html index fffda4570d71bade9f81cad65fb569efccf59908..5cb5a697ec2b2a9b5557c8501d0ae9ddcf784ccc 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,6 +1,6 @@ - + Menu diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5da945e5b0583e6019d39e3583f2eaf7b4c865c6..90896ac20bbb4484d4f41a62e57e7794a4f70634 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,6 +3,10 @@ import { Component } from '@angular/core'; import { Platform } from '@ionic/angular'; import { SplashScreen } from '@ionic-native/splash-screen/ngx'; import { StatusBar } from '@ionic-native/status-bar/ngx'; +import { Storage } from '@ionic/storage'; +import { Router } from '@angular/router'; + +import { RestService } from './rest.service'; @Component({ selector: 'app-root', @@ -10,12 +14,20 @@ import { StatusBar } from '@ionic-native/status-bar/ngx'; styleUrls: ['app.component.scss'] }) export class AppComponent { + + isLoginPage = false; + public appPages = [ { title: 'Home', url: '/home', icon: 'home' }, + { + title: 'My Reservation', + url: '/myreservation', + icon: 'clipboard' + }, { title: 'Logout', url: '/login', @@ -26,9 +38,26 @@ export class AppComponent { constructor( private platform: Platform, private splashScreen: SplashScreen, - private statusBar: StatusBar - ) { + private statusBar: StatusBar, + public restService: RestService, + private storage: Storage, + private router: Router) { + this.initializeApp(); + + let href = window.location.pathname + if(href === "/login") { + this.restService.isLoginPage = true; + } else { + this.restService.isLoginPage = false; + } + this.storage.get('token').then((token) => { + if(token === "") { + this.router.navigateByUrl('/login'); + } else { + this.restService.isUserLoggedIn = true; + } + }); } initializeApp() { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0ed635fc9802fafa9b7b5fd5af032454c0252b36..3f95b3c32a84902f9493f17f243b4b8a43f28805 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -15,6 +15,7 @@ import { NativeGeocoder, NativeGeocoderOptions } from '@ionic-native/native-geoc import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { RestService } from './rest.service'; +import { ToastService } from './services/toast.service'; @NgModule({ declarations: [AppComponent], @@ -32,6 +33,7 @@ import { RestService } from './rest.service'; SplashScreen, RestService, NativeGeocoder, + ToastService, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ], bootstrap: [AppComponent] diff --git a/src/app/auth/login/login.page.ts b/src/app/auth/login/login.page.ts index 66828cf72a9c69ae3ecf1e289d84e5f17d9b65f6..460cad5bd7c583070d6770fde2a36076cc8a6b03 100644 --- a/src/app/auth/login/login.page.ts +++ b/src/app/auth/login/login.page.ts @@ -38,17 +38,16 @@ export class LoginPage implements OnInit { }); this.loginApi .subscribe((data) => { - console.log('my data: ', data); + //console.log('my data: ', data); this.restService.setToken(data.token); + this.restService.isLoginPage = false; this.router.navigateByUrl('/home'); }, (error) => { - console.log(error); + console.log(JSON.stringify(error)); this.correctCredentials = true; }); } register() { this.router.navigateByUrl('/register'); - - } } diff --git a/src/app/auth/register/register.page.html b/src/app/auth/register/register.page.html index 9ce0ad141718a58abf5d941363c4b1f34baf7abf..49983a6d199120b9ceb89e370573fce038b5970f 100644 --- a/src/app/auth/register/register.page.html +++ b/src/app/auth/register/register.page.html @@ -29,7 +29,7 @@ -
+
Wrong Credentials !
diff --git a/src/app/auth/register/register.page.ts b/src/app/auth/register/register.page.ts index 2809c34fc7b45562d57a936d8c5da0f8e2d15a5e..bfa94bb6f01b5d801e316b4612dfb350f9aa6a58 100644 --- a/src/app/auth/register/register.page.ts +++ b/src/app/auth/register/register.page.ts @@ -1,5 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; +import { HttpClient } from '@angular/common/http'; +import { RestService } from 'src/app/rest.service'; +import { Router } from '@angular/router'; @Component({ selector: 'app-register', @@ -7,14 +10,33 @@ import { Observable } from 'rxjs'; styleUrls: ['./register.page.scss'], }) export class RegisterPage implements OnInit { - httpClient: any; + registerApi: Observable; - restService: any; - router: any; + correctCredentials: boolean; - constructor() { } + email: ""; + password: ""; + lastName: ""; + firstName: ""; + constructor(private router: Router, public httpClient: HttpClient, public restService: RestService) { } ngOnInit() { } - + submitRegister() { + this.registerApi = this.httpClient.post('http://193.196.52.237:8081/register', { + "email": this.email, + "password": this.password, + "firstname": this.firstName, + "lastname": this.lastName + }); + this.registerApi + .subscribe((data) => { + console.log('my data: ', data); + this.restService.setToken(data.token); + this.router.navigateByUrl('/login'); + }, (error) => { + console.log(error); + this.correctCredentials = true; + }); + } } diff --git a/src/app/hirebike/hirebike-routing.module.ts b/src/app/hirebike/hirebike-routing.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..4f63dd01946ae35d661c931f77db12c1303f062c --- /dev/null +++ b/src/app/hirebike/hirebike-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +import { HirebikePage } from './hirebike.page'; + +const routes: Routes = [ + { + path: '', + component: HirebikePage + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class HirebikePageRoutingModule {} diff --git a/src/app/hirebike/hirebike.module.ts b/src/app/hirebike/hirebike.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..7e9eb00d798ae46de0f4145b26cdd4d7cd55bae9 --- /dev/null +++ b/src/app/hirebike/hirebike.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 { HirebikePageRoutingModule } from './hirebike-routing.module'; + +import { HirebikePage } from './hirebike.page'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + HirebikePageRoutingModule + ], + declarations: [HirebikePage] +}) +export class HirebikePageModule {} diff --git a/src/app/hirebike/hirebike.page.html b/src/app/hirebike/hirebike.page.html new file mode 100644 index 0000000000000000000000000000000000000000..d5d6e505aae5a84f7be8f97926637de320665108 --- /dev/null +++ b/src/app/hirebike/hirebike.page.html @@ -0,0 +1,60 @@ + + + + + + + Hire Bike + + + + + +
+ + + +
+
+
+ +
+
+
+ + + Bike Name + {{bikeDetails.name}} + + + Bike Location + {{bikeDetails.address}} + + + + Start Trip + + + +
+
+
+
+
+
+ + + Any Problems? + + + + + + Cancel Trip + + + +
+
+
+
\ No newline at end of file diff --git a/src/app/hirebike/hirebike.page.scss b/src/app/hirebike/hirebike.page.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/hirebike/hirebike.page.spec.ts b/src/app/hirebike/hirebike.page.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..60af364821581511ff3e0c320629f861a0533a66 --- /dev/null +++ b/src/app/hirebike/hirebike.page.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { HirebikePage } from './hirebike.page'; + +describe('HirebikePage', () => { + let component: HirebikePage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HirebikePage ], + imports: [IonicModule.forRoot()] + }).compileComponents(); + + fixture = TestBed.createComponent(HirebikePage); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/hirebike/hirebike.page.ts b/src/app/hirebike/hirebike.page.ts new file mode 100644 index 0000000000000000000000000000000000000000..90b941320dfa7104028c84408ecb62d9109c3cab --- /dev/null +++ b/src/app/hirebike/hirebike.page.ts @@ -0,0 +1,271 @@ +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-hirebike', + templateUrl: './hirebike.page.html', + styleUrls: ['./hirebike.page.scss'], +}) +export class HirebikePage implements OnInit { + + private platform: any; + private map: any; + // Get an instance of the routing service: + private mapRouter: any; + + reservedBike: any = {}; + bikeDetails: any = {}; + isBikeHired=false; + + 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)); + }); + } + startTrip(){ + + this.storage.get('token').then((token) => { + let url = 'http://193.196.52.237:8081/rent' + '?bikeId=' + this.bikeDetails.id; + const headers = new HttpHeaders().set("Authorization", "Bearer " + token); + let bikeApi = this.httpClient.get(url, { headers }); + bikeApi.subscribe((resp) => { + console.log('my data: ', resp); + this.toastService.showToast("Trip Started"); + this.isBikeHired=true; + }, (error) => { + console.log(error) + this.toastService.showToast("Unable to Hire Bike") + }); + }); + + } + + + + 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); + } + }; + + +} diff --git a/src/app/home/home.page.html b/src/app/home/home.page.html index 8c66dabc54b9f0ff9eba6886e8d9892248d402bb..a3d9d06a47f3e661ba99b1687f612796dc8b83cc 100644 --- a/src/app/home/home.page.html +++ b/src/app/home/home.page.html @@ -12,12 +12,15 @@ + +
+ @@ -26,22 +29,90 @@ -
+
-
- {{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