Hero - ionic II L9
Tue Jun 18 2024 11:43:37 GMT+0000 (Coordinated Universal Time)
Saved by @iamkatmakhafola
//Service // Service for handling Hero-related API calls import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { map, Observable, Subject } from 'rxjs'; import { Hero } from '../shared/hero'; @Injectable({ providedIn: 'root' }) export class HeroService { // Base URL for the API apiUrl = 'http://localhost:5116/api/' // HTTP options with headers httpOptions = { headers: new HttpHeaders({ ContentType: 'application/json' }) } constructor(private _httpClient: HttpClient) { } // Method to get all heroes from the API getHeroes(): Observable<Hero[]> { return this._httpClient.get<Hero[]>(`${this.apiUrl}Hero/GetAllHeroes`) .pipe(map(result => result)) } // Method to get a specific hero by ID from the API getHero(heroId: number) { return this._httpClient.get(`${this.apiUrl}Hero/GetHero` + "/" + heroId) .pipe(map(result => result)) } } //Home page //HTML <ion-header [translucent]="true"> <ion-toolbar> <ion-title> Home </ion-title> </ion-toolbar> </ion-header> <ion-content> //Display skeleton loading cards if Heroes data is not available --> <div *ngIf="!Heroes"> <ion-card> <ion-skeleton-text style="height:200px;" animated></ion-skeleton-text> <ion-card-header></ion-card-header> </ion-card> //Repeated skeleton cards for loading state --> <ion-card> <ion-skeleton-text style="height:200px;" animated></ion-skeleton-text> <ion-card-header></ion-card-header> </ion-card> <ion-card> <ion-skeleton-text style="height:200px;" animated></ion-skeleton-text> <ion-card-header></ion-card-header> </ion-card> <ion-card> <ion-skeleton-text style="height:200px;" animated></ion-skeleton-text> <ion-card-header> </ion-card-header> </ion-card> </div> //Pull-to-refresh functionality --> <ion-refresher slot="fixed" (ionRefresh)="refreshHeroes($event)"> <ion-refresher-content refreshingText="Loading Heroes..."></ion-refresher-content> </ion-refresher> //Display hero cards when Heroes data is available --> <ion-card button *ngFor="let hero of (Heroes | async)" [routerLink]="['hero-detail', hero.heroId]"> <ion-img [src]="hero.imageBase64"></ion-img> </ion-card> </ion-content> //TS import { Component } from '@angular/core'; import { IonicModule, ToastController } from '@ionic/angular'; import { ExploreContainerComponent } from '../explore-container/explore-container.component'; import { Hero } from '../shared/hero'; import { HeroService } from '../services/hero.service'; import { AppModule } from '../app.module'; import { CommonModule } from '@angular/common'; import { Observable } from 'rxjs'; import { RouterLink } from '@angular/router'; @Component({ selector: 'app-tab1', templateUrl: 'tab1.page.html', styleUrls: ['tab1.page.scss'], standalone: true, imports: [IonicModule, ExploreContainerComponent, AppModule, CommonModule, RouterLink], }) export class Tab1Page { // Observable to hold the list of heroes Heroes: Observable<Hero[]>; constructor(private _toastController: ToastController, private _heroService: HeroService) { // Fetching heroes from the service this.Heroes = this._heroService.getHeroes(); } ngOnInit() { } // Method to refresh the list of heroes refreshHeroes(event:any){ this.Heroes = this._heroService.getHeroes(); // Complete the refresh event event.target.complete(); // Show a toast notification const toast = this._toastController.create({ message: "Heroes are refreshed", duration: 3000, position: "bottom" }) toast.then((toastMessage) => { toastMessage.present(); }) } } //hero detail page //HTML <ion-header [translucent]="true"> <ion-toolbar> <ion-buttons slot="start"> <ion-back-button></ion-back-button> </ion-buttons> <ion-title></ion-title> </ion-toolbar> </ion-header> <ion-content> //Display hero image --> <ion-img src={{heroDetail?.imageBase64}}></ion-img> //Hero details card --> <ion-card no-margin> <ion-card-header> <ion-card-title> {{heroDetail?.name}} </ion-card-title> </ion-card-header> </ion-card> <ion-card> <ion-list lines="none"> //Display hero's age --> <ion-item> <ion-label>Age</ion-label> <ion-chip color="primary">{{heroDetail?.age}}</ion-chip> </ion-item> //Display hero's height --> <ion-item> <ion-label>Height</ion-label> <ion-chip color="secondary">{{heroDetail?.height}}</ion-chip> </ion-item> //Display hero's birthday --> <ion-item> <ion-label>Birthday</ion-label> <ion-chip>{{heroDetail?.birthday}}</ion-chip> </ion-item> </ion-list> </ion-card> //Floating action button to open modal for hero status --> <ion-fab vertical="top" horizontal="end" slot="fixed"> <ion-fab-button (click)="openModal(heroDetail?.isAlive)"> <ion-icon name="eye"></ion-icon> </ion-fab-button> </ion-fab> </ion-content> //TS import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IonicModule, ModalController, ToastController } from '@ionic/angular'; import { HeroService } from '../services/hero.service'; import { ActivatedRoute } from '@angular/router'; import { HerostatusPage } from '../herostatus/herostatus.page'; @Component({ selector: 'app-hero-detail', templateUrl: './hero-detail.page.html', styleUrls: ['./hero-detail.page.scss'], standalone: true, imports: [IonicModule, CommonModule, FormsModule] }) export class HeroDetailPage implements OnInit { // Variable to hold the hero details heroDetail: any; constructor( private _toastController: ToastController, private _heroService: HeroService, private _modal: ModalController, private route: ActivatedRoute ) { // Fetch the hero details based on the hero ID from the route parameters this._heroService.getHero(+this.route.snapshot.params['heroId']).subscribe(result => { this.heroDetail = result // Show a toast notification const toast = this._toastController.create({ message: "Hero " + this.heroDetail.name + " is viewable", duration: 3000, position: "bottom" }) toast.then((toastMessage) => { toastMessage.present(); }) }) } ngOnInit(): void { } // Method to open a modal showing the hero's status (alive or dead) async openModal(status: boolean) { const statusModal = await this._modal.create({ component: HerostatusPage, componentProps: { value: status } }) return await statusModal.present() } } //Hero status page //HTML <ion-header [translucent]="true"> <ion-toolbar> <ion-title>Hero Status</ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-fab vertical="center" horizontal="center"> <ion-fab-button *ngIf="value"> <ion-icon name="happy-outline" *ngIf="value"> </ion-icon> Alive </ion-fab-button> <ion-fab-button *ngIf="!value"> <ion-icon name="sad-outline" *ngIf="!value"></ion-icon> Dead </ion-fab-button> </ion-fab> <ion-button (click)="closeModal()" class="container" color="danger"> <ion-icon name="close-circle-outline" size="large"></ion-icon> </ion-button> </ion-content> //TS import { Component, Input, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IonicModule, ModalController } from '@ionic/angular'; @Component({ selector: 'app-herostatus', templateUrl: './herostatus.page.html', styleUrls: ['./herostatus.page.scss'], standalone: true, imports: [IonicModule, CommonModule, FormsModule] }) export class HerostatusPage implements OnInit { // Input property to receive the hero's status (alive or dead) @Input() value: any; constructor(private _modal: ModalController) { } ngOnInit() { } // Method to close the modal closeModal() { this._modal.dismiss() } }
Comments