diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index d3941421c3aa9bc5122e740c5a34c005febd1a58..f5d55a619abeb6ca9adc9a7c132475a164b78160 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,36 +1,40 @@ -import { NgModule } from '@angular/core'; -import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; - -const routes: Routes = [ - { - path: '', - redirectTo: 'login', - pathMatch: 'full' - }, - { - path: 'home', - loadChildren: () => import('./home/home.module').then(m => m.HomePageModule) - }, - { - path: 'list', - loadChildren: () => import('./list/list.module').then(m => m.ListPageModule) - }, - { - path: 'login', - loadChildren: () => import('./auth/login/login.module').then( m => m.LoginPageModule) - }, - { - path: 'register', - loadChildren: () => import('./auth/register/register.module').then( m => m.RegisterPageModule) +import { NgModule } from '@angular/core'; +import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; + +const routes: Routes = [ + { + path: '', + redirectTo: 'login', + pathMatch: 'full' + }, + { + path: 'home', + loadChildren: () => import('./home/home.module').then(m => m.HomePageModule) + }, + { + path: 'list', + loadChildren: () => import('./list/list.module').then(m => m.ListPageModule) + }, + { + 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: 'my-reservation', + loadChildren: () => import('./my-reservation/my-reservation.module').then( m => m.MyReservationPageModule) } - - -]; -@NgModule({ - imports: [ - RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) - ], - exports: [RouterModule] -}) -export class AppRoutingModule {} + + +]; + +@NgModule({ + imports: [ + RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) + ], + exports: [RouterModule] +}) +export class AppRoutingModule {} diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5da945e5b0583e6019d39e3583f2eaf7b4c865c6..84ee14ab857b25596181d25c6cdd5e8a7e6f6c77 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -16,6 +16,11 @@ export class AppComponent { url: '/home', icon: 'home' }, + { + title: 'My Reservation', + url: '/my-reservation', + icon: 'history' + }, { title: 'Logout', url: '/login', diff --git a/src/app/home/home.page.html b/src/app/home/home.page.html index 59baf6927de11e15f88a2e24ccf7b344d6b3ccdf..40558160ced44778a7f0d4a5c191cd2f9a970f23 100644 --- a/src/app/home/home.page.html +++ b/src/app/home/home.page.html @@ -95,7 +95,7 @@ {{selectedBike.distance + "m"}} </ion-col> </ion-row> - <ion-row *ngIf="!isBikeReserved"> + <ion-row> <ion-col> <ion-button size="medium" expand="block" (click)="reserveBike()">Reserve</ion-button> </ion-col> @@ -103,14 +103,7 @@ <ion-button size="medium" expand="block" (click)="navigatetoBike()">Navigate</ion-button> </ion-col> </ion-row> - <ion-row *ngIf="isBikeReserved"> - <ion-col> - <ion-button size="medium" expand="block" (click)="hireBike()">Hire</ion-button> - </ion-col> - <ion-col> - <ion-button size="medium" expand="block" (click)="cancelReservation()">Cancel Reservation</ion-button> - </ion-col> - </ion-row> + </ion-grid> </div> </div> diff --git a/src/app/home/home.page.ts b/src/app/home/home.page.ts index 1df890bff5829f2038e31a5d0e5c6bae181c9597..40be6f65051d979455fc3b61ad62e373053d2269 100644 --- a/src/app/home/home.page.ts +++ b/src/app/home/home.page.ts @@ -5,6 +5,7 @@ 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; @@ -48,7 +49,8 @@ export class HomePage { public restService: RestService, public httpClient: HttpClient, private storage: Storage, - private toastService: ToastService) { + private toastService: ToastService, + private router: Router) { this.platform = new H.service.Platform({ 'apikey': 'tiVTgBnPbgV1spie5U2MSy-obhD9r2sGiOCbBzFY2_k' @@ -245,25 +247,18 @@ export class HomePage { console.log('my data: ', resp); this.isBikeReserved=true; this.toastService.showToast("Reservation Successful!"); + this.router.navigateByUrl('/my-reservation'); + //this.router.navigate(['/my-reservation', {bikeId: this.selectedBike.id}]); }, (error) => { console.log(error) this.toastService.showToast("Only one bike may be reserved or rented at a time") }); }); - - } - cancelReservation() { - 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.delete(url, { headers }); - this.bikeApi.subscribe((resp) => { - console.log('my data: ', resp); - this.isBikeReserved=false; - }, (error) => console.log(error)); - }); - + + + } + } diff --git a/src/app/my-reservation/my-reservation-routing.module.ts b/src/app/my-reservation/my-reservation-routing.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..32b0c2ec5eb1f005ecdfe5a54ee29624f7833427 --- /dev/null +++ b/src/app/my-reservation/my-reservation-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +import { MyReservationPage } from './my-reservation.page'; + +const routes: Routes = [ + { + path: '', + component: MyReservationPage + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class MyReservationPageRoutingModule {} diff --git a/src/app/my-reservation/my-reservation.module.ts b/src/app/my-reservation/my-reservation.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..09ffd83caad3a1866a73ee3b276e7697a7829ce9 --- /dev/null +++ b/src/app/my-reservation/my-reservation.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 './my-reservation-routing.module'; + +import { MyReservationPage } from './my-reservation.page'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + MyReservationPageRoutingModule + ], + declarations: [MyReservationPage] +}) +export class MyReservationPageModule {} diff --git a/src/app/my-reservation/my-reservation.page.html b/src/app/my-reservation/my-reservation.page.html new file mode 100644 index 0000000000000000000000000000000000000000..9f90662a88662e08ddf53353a425aa4fe43760c7 --- /dev/null +++ b/src/app/my-reservation/my-reservation.page.html @@ -0,0 +1,83 @@ +<ion-header> + <ion-toolbar> + <ion-buttons slot="start"> + <ion-menu-button></ion-menu-button> + </ion-buttons> + <ion-title slot="start"> + My Reservation + </ion-title> + <ion-item class="checkbox-wrapper"> + <!--ion-checkbox class="checkbox" [(ngModel)]="is3DChecked" (click)="toggle3DMaps()"></ion-checkbox--> + <ion-label class="text" (click)="enable3DMaps()">3D</ion-label> + </ion-item> + </ion-toolbar> +</ion-header> +<ion-content> + + <div #mapElement2d style="width: 100%; height: 100%" id="mapContainer" *ngIf="!is3DChecked"></div> + <div #mapElement3d style="width: 100%; height: 100%" id="mapContainer" *ngIf="is3DChecked"></div> + <!--div #mapElement style="width: 100%; height: 100%" id="mapContainer"></div--> + <ion-fab vertical="bottom" horizontal="end" (click)="getCurrentPosition()" slot="fixed"> + <ion-fab-button> + <ion-icon name="locate"></ion-icon> + </ion-fab-button> + </ion-fab> +</ion-content> + +<ion-footer> + + + + <div class="bike-details-container"> + <div class="inner"> + <div class="button-container"> + <ion-grid> + <ion-row> + <ion-col> + Bike Name + </ion-col> + <!-- <ion-col> + {{selectedBike.name}} + </ion-col> --> + </ion-row> + <ion-row> + <ion-col> + Battery Level + </ion-col> + <!-- <ion-col> + + <ion-icon class="battery-icon" name="battery-charging"></ion-icon> + {{selectedBike.batteryPercentage + " %"}} + </ion-col> --> + </ion-row> + <ion-row> + <ion-col> + Bike Location + </ion-col> + <!-- <ion-col> + {{selectedBike.address}} + </ion-col> --> + </ion-row> + <ion-row> + <ion-col> + Bike Distance + </ion-col> + <!-- <ion-col> + {{selectedBike.distance + "m"}} + </ion-col> --> + </ion-row> + + <ion-row> + <ion-col> + <ion-button size="medium" expand="block" (click)="hireBike()">Hire</ion-button> + </ion-col> + <ion-col> + <ion-button size="medium" expand="block" (click)="cancelReservation()">Cancel Reservation</ion-button> + </ion-col> + </ion-row> + </ion-grid> + </div> + </div> + + </div> +</ion-footer> \ No newline at end of file diff --git a/src/app/my-reservation/my-reservation.page.scss b/src/app/my-reservation/my-reservation.page.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/my-reservation/my-reservation.page.spec.ts b/src/app/my-reservation/my-reservation.page.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..19abc3e6c31eeceed22881b4a62d1cce027dd89a --- /dev/null +++ b/src/app/my-reservation/my-reservation.page.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { MyReservationPage } from './my-reservation.page'; + +describe('MyReservationPage', () => { + let component: MyReservationPage; + let fixture: ComponentFixture<MyReservationPage>; + + 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/my-reservation/my-reservation.page.ts b/src/app/my-reservation/my-reservation.page.ts new file mode 100644 index 0000000000000000000000000000000000000000..3d8e1ca423a6b7c20ca3c7934d234504ed51331d --- /dev/null +++ b/src/app/my-reservation/my-reservation.page.ts @@ -0,0 +1,229 @@ +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 { ActivatedRoute } from '@angular/router'; + + +declare var H: any; +@Component({ + selector: 'app-my-reservation', + templateUrl: './my-reservation.page.html', + styleUrls: ['./my-reservation.page.scss'], +}) +export class MyReservationPage implements OnInit { + private platform: any; + private map: any; + bikes = []; + bikeApi: Observable<any>; + + private currentLocation = { lat: 0, lng: 0 }; + + public is3DChecked = false; + + public bikeId =0; + + + public tempArr = [1, 2]; + public locationArr = [{ lat: 48.778409, lng: 9.179252 }, + { lat: 48.780926, lng: 9.173456 }, + { lat: 48.775174, lng: 9.175459 }, + { lat: 48.793704, lng: 9.191112 }] + public arrayLanLon = { lat: 0, lng: 0 }; + @ViewChild("mapElement2d", { static: false }) + public mapElement2d: ElementRef; + + @ViewChild("mapElement3d", { static: false }) + public mapElement3d: ElementRef; + + + //@ViewChild("mapElement", { static: false }) + //public mapElement: ElementRef; + + constructor(private geolocation: Geolocation, + public restService: RestService, + public httpClient: HttpClient, + private storage: Storage, + private toastService: ToastService, + private route: ActivatedRoute) { + + + this.platform = new H.service.Platform({ + 'apikey': 'tiVTgBnPbgV1spie5U2MSy-obhD9r2sGiOCbBzFY2_k' + }); + } + + ngOnInit() { + /* this.route.queryParams + .filter (params => params.bikeId) + .subscribe(params => { + console.log(params); // {order: "popular"} + + this.bikeId = params.bikeId; + console.log(this.bikeId); // popular + }); */ + + } + + ngAfterViewInit() { + setTimeout(() => { + this.loadmap("2D"); + }, 1000); + + window.addEventListener('resize', () => this.map.getViewPort().resize()); + } + + g + + + + loadmap(style) { + // Obtain the default map types from the platform object + var mapStyle = "raster"; + var mapElement = "mapElement2d"; + if (style === "3D") { + mapStyle = "vector"; + mapElement = "mapElement3d"; + } + var defaultLayers = this.platform.createDefaultLayers(); + this.map = new H.Map( + this[mapElement].nativeElement, + defaultLayers[mapStyle].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'); + if (style === "3D") { + this.map.getViewModel().setLookAtData({ tilt: 60 }); + } + 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']; + for (let i = 0; i < this.bikes.length; i++) { + if(this.bikes[i].batteryPercentage<100 &&this.bikes[i].batteryPercentage>=75){ + this.addMarker(Number(this.bikes[i].lat), Number(this.bikes[i].lon), img[0]); + } + else if(this.bikes[i].batteryPercentage<75 &&this.bikes[i].batteryPercentage>=50){ + this.addMarker(Number(this.bikes[i].lat), Number(this.bikes[i].lon), img[1]); + } + else if(this.bikes[i].batteryPercentage<50 &&this.bikes[i].batteryPercentage>=25){ + this.addMarker(Number(this.bikes[i].lat), Number(this.bikes[i].lon), img[2]); + }else if(this.bikes[i].batteryPercentage<25 &&this.bikes[i].batteryPercentage>=0){ + this.addMarker(Number(this.bikes[i].lat), Number(this.bikes[i].lon), img[3]); + } + //console.log("rroni", this.bikes[i].lat); + // this.addMarker(Number(this.bikes[i].lat), Number(this.bikes[i].lon), img[0]); + // this.addMarker(Number(48.78077362), 9.17782398, img[i % 3]); + //alert(this.bikes[i].lat); + } + } + getCurrentPosition() { + this.getLocation(this.map); + } + 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); + }, 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 }); + } + + expandBikeList() { + for (let i = 0; i < 20; i++) { + this.tempArr.push(i + 3); + } + } + + 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); + } + + toggle3DMaps() { + console.log(this.is3DChecked); + if (!this.is3DChecked) { + setTimeout(() => { + this.loadmap("3D"); + }, 1000); + } + } + + enable3DMaps() { + this.is3DChecked = true; + setTimeout(() => { + this.loadmap("3D"); + }, 100); + } + + cancelReservation() { + this.storage.get('token').then((token) => { + let url = 'http://193.196.52.237:8081/reservation' + '?bikeId=' + this.bikeId; + const headers = new HttpHeaders().set("Authorization", "Bearer " + token); + this.bikeApi = this.httpClient.delete(url, { headers }); + this.bikeApi.subscribe((resp) => { + console.log('my data: ', resp); + + }, (error) => console.log(error)); + }); + + } +} diff --git a/src/assets/images/ReservedBike.svg b/src/assets/images/ReservedBike.svg new file mode 100644 index 0000000000000000000000000000000000000000..0751d0e9f850bee81fbb3181ba219396f99da749 --- /dev/null +++ b/src/assets/images/ReservedBike.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M376 186h-20v-40c0-55-45-100-100-100S156 91 156 146v40h-20c-22.002 0-40 17.998-40 40v200c0 22.002 17.998 40 40 40h240c22.002 0 40-17.998 40-40V226c0-22.002-17.998-40-40-40zM256 368c-22.002 0-40-17.998-40-40s17.998-40 40-40 40 17.998 40 40-17.998 40-40 40zm62.002-182H193.998v-40c0-34.004 28.003-62.002 62.002-62.002 34.004 0 62.002 27.998 62.002 62.002v40z"/></svg> \ No newline at end of file