This commit is contained in:
csimonis 2024-11-19 08:15:13 +01:00
parent 1b1224cba0
commit 20c04abe4f
8 changed files with 102 additions and 30 deletions

View File

@ -9,8 +9,6 @@ import {RouterOutlet} from "@angular/router";
standalone: true, standalone: true,
imports: [HotelsComponent, IdkComponent, RouterOutlet], imports: [HotelsComponent, IdkComponent, RouterOutlet],
template: ` template: `
<app-hotels />
<app-idk />
<router-outlet /> <router-outlet />
` `
}) })

View File

@ -1,15 +1,21 @@
import { Routes } from '@angular/router'; import { Routes } from '@angular/router';
import {HotelsComponent} from "./hotel/hotels.component"; import {HotelsComponent} from "./hotel/hotels.component";
import {HotelComponent} from "./hotel/hotel.component"; import {HotelComponent} from "./hotel/hotel.component";
import {CreateHotelComponent} from "./hotel/create-hotel.component";
export const routes: Routes = [ export const routes: Routes = [
{ {
path: '/hotels', path: 'hotels',
component: HotelsComponent, component: HotelsComponent,
title: 'Hotels', title: 'Hotels',
}, },
{ {
path: '/hotels/{id}', path: 'hotels/new',
component: CreateHotelComponent,
title: 'New Hotel'
},
{
path: 'hotels/:hotelId',
component: HotelComponent, component: HotelComponent,
title: 'Hotel', title: 'Hotel',
} }

View File

@ -0,0 +1,35 @@
import { Component } from '@angular/core';
import {FormsModule} from "@angular/forms";
@Component({
selector: 'app-create-hotel',
standalone: true,
imports: [
FormsModule
],
template: `
<ng-form>
<label for="name">Name</label>
<br>
<input id="name" type="text">
<br>
<label for="description">Description</label>
<br>
<input id="description" type="text">
<br>
<label for="price">Price</label>
<br>
<input id="price" type="number">
<br>
<label for="rating">Rating</label>
<br>
<input id="rating" type="number">
<br>
<br>
<button type="submit">Submit</button>
</ng-form>
`,
})
export class CreateHotelComponent {
}

View File

@ -1,9 +1,11 @@
import {Component, Input} from "@angular/core"; import {Component, inject, Input, OnInit} from "@angular/core";
import {Hotel} from "./hotel" import {Hotel} from "./hotel"
import {CurrencyPipe} from "@angular/common"; import {CurrencyPipe, NgOptimizedImage} from "@angular/common";
import {Lang} from "../idek/lang"; import {Lang} from "../idek/lang";
import {StarComponent} from "../star/star.component"; import {StarComponent} from "../star/star.component";
import {ActivatedRoute} from "@angular/router";
import {HotelService} from "../service/hotel.service"; import {HotelService} from "../service/hotel.service";
import {catchError, EMPTY, throwError} from "rxjs";
@Component({ @Component({
@ -11,24 +13,46 @@ import {HotelService} from "../service/hotel.service";
selector: 'app-hotel', selector: 'app-hotel',
imports: [ imports: [
CurrencyPipe, CurrencyPipe,
StarComponent StarComponent,
NgOptimizedImage
], ],
template: ` template: `
<div style="border: white 2px; border-radius: 2px"> <div style="border: white 2px; border-radius: 2px">
<p class="name">Name: {{ hotel.hotelName }}</p> @if (hotel && !alert) {
<p>Beschreibung: {{ hotel.description }}</p> <p class="name">Name: {{ hotel.hotelName }}</p>
<p>Preis: {{ hotel.price | currency: currency.currency : 'symbol' : '2.2-2' : currency.code }}/nacht</p> <p>Beschreibung: {{ hotel.description }}</p>
<p>Sterne: <app-star [rating]="hotel.rating"></app-star></p> <p>Preis: {{ hotel.price | currency: currency.currency : 'symbol' : '2.2-2' : currency.code }}/nacht</p>
<img width="64" height="64" src="{{hotel.imageUrl}}"> <p>Sterne:
<app-star [rating]="hotel.rating"></app-star>
</p>
<img width="64" height="64" src="{{hotel.imageUrl}}">
} @else if(alert) {
<h2>{{alert}}</h2>
} @else {
<h2>loading</h2>
}
</div> </div>
` `
}) })
export class HotelComponent { export class HotelComponent implements OnInit {
@Input() protected currency: Lang = {name: 'de', code: 'de-DE', currency: 'EUR'}
public currency: Lang = {name: 'de', code: 'de-DE', currency: 'EUR'}
@Input()
public hotel!: Hotel;
constructor() { protected hotel!: Hotel;
protected alert: string|undefined
private route: ActivatedRoute = inject(ActivatedRoute);
private hotelService: HotelService = inject(HotelService);
ngOnInit(): void {
const hotelId = this.route.snapshot.params['hotelId'];
this.hotelService.getHotelById(hotelId)
.pipe(catchError((err) => {
this.alert = `Hotel could not be retrieved: ${err.message}`
return EMPTY;
}))
.subscribe({next: (hotel: Hotel) => {this.hotel = hotel}})
} }
} }

View File

@ -1,5 +1,5 @@
export interface Hotel { export interface Hotel {
hotelId: number; id: number;
hotelName: string; hotelName: string;
description: string; description: string;
price: number; price: number;

View File

@ -4,9 +4,11 @@ import {Hotel} from "./hotel";
import {FormsModule} from "@angular/forms"; import {FormsModule} from "@angular/forms";
import {Lang} from "../idek/lang"; import {Lang} from "../idek/lang";
import {HotelService} from "../service/hotel.service"; import {HotelService} from "../service/hotel.service";
import {Observable} from "rxjs"; import {filter, Observable, toArray} from "rxjs";
import {AsyncPipe} from "@angular/common"; import {AsyncPipe} from "@angular/common";
import {CurrencyComponent} from "../currency/currency.component"; import {CurrencyComponent} from "../currency/currency.component";
import {RouterLink} from "@angular/router";
import {StarComponent} from "../star/star.component";
@Component({ @Component({
standalone: true, standalone: true,
@ -15,14 +17,17 @@ import {CurrencyComponent} from "../currency/currency.component";
<form> <form>
<input name="search" [ngModel]="search" (ngModelChange)="searchEvent($event)"> <input name="search" [ngModel]="search" (ngModelChange)="searchEvent($event)">
</form> </form>
@for (hotel of (matchingHotels | async); track hotel.hotelId) { @for (hotel of (matchingHotels | async); track hotel.id) {
<app-hotel [hotel]="hotel" [currency]="currency"></app-hotel> <div>{{hotel.hotelName}}</div>
<hr> <img src="{{hotel.imageUrl}}" alt="{{hotel.hotelName}}" height="64" width="64">
<br>
<button routerLink="{{hotel.id}}">Details</button>
<hr>
} @empty { } @empty {
<h1>no matching results for {{search}}</h1> <h1>no matching results for {{ search }}</h1>
} }
`, `,
imports: [FormsModule, HotelComponent, AsyncPipe, CurrencyComponent], imports: [FormsModule, HotelComponent, AsyncPipe, CurrencyComponent, RouterLink, StarComponent],
providers: [HotelService], providers: [HotelService],
selector: 'app-hotels' selector: 'app-hotels'
}) })
@ -38,6 +43,6 @@ export class HotelsComponent {
public searchEvent(input: string) { public searchEvent(input: string) {
this.search = input.toLowerCase(); this.search = input.toLowerCase();
//this.matchingHotels.pipe(filter((hotel: Hotel) => hotel.hotelName.toLowerCase().includes(input.toLowerCase())));
} }
} }

View File

@ -6,7 +6,7 @@ export class HotelDataService implements InMemoryDbService{
createDb(): Record<string, Hotel[]> { createDb(): Record<string, Hotel[]> {
const hotels: Hotel[] = [ const hotels: Hotel[] = [
{ {
"hotelId": 1, "id": 1,
"hotelName": "Buea süßes Leben", "hotelName": "Buea süßes Leben",
"description": "Schöne Aussicht am Meer", "description": "Schöne Aussicht am Meer",
"price": 230.5, "price": 230.5,
@ -14,7 +14,7 @@ export class HotelDataService implements InMemoryDbService{
"rating": 3.5 "rating": 3.5
}, },
{ {
"hotelId": 2, "id": 2,
"hotelName": "Marrakesch", "hotelName": "Marrakesch",
"description": "Genießen Sie den Blick auf die Berge", "description": "Genießen Sie den Blick auf die Berge",
"price": 145.5, "price": 145.5,
@ -22,7 +22,7 @@ export class HotelDataService implements InMemoryDbService{
"rating": 5 "rating": 5
}, },
{ {
"hotelId": 3, "id": 3,
"hotelName": "Abuja neuer Palast", "hotelName": "Abuja neuer Palast",
"description": "Kompletter Aufenthalt mit Autoservice", "description": "Kompletter Aufenthalt mit Autoservice",
"price": 120.12, "price": 120.12,
@ -30,7 +30,7 @@ export class HotelDataService implements InMemoryDbService{
"rating": 4 "rating": 4
}, },
{ {
"hotelId": 4, "id": 4,
"hotelName": "OUR Hotel", "hotelName": "OUR Hotel",
"description": "Wunderschönes Ambiente für Ihren Aufenthalt", "description": "Wunderschönes Ambiente für Ihren Aufenthalt",
"price": 135.12, "price": 135.12,

View File

@ -12,4 +12,8 @@ export class HotelService {
public getHotels(): Observable<Hotel[]> { public getHotels(): Observable<Hotel[]> {
return this.httpClient.get<Hotel[]>('/api/hotels'); return this.httpClient.get<Hotel[]>('/api/hotels');
} }
public getHotelById(id: number): Observable<Hotel> {
return this.httpClient.get<Hotel>(`/api/hotels/${id}`);
}
} }