feat: add hotel details and list components with routing
This commit is contained in:
parent
d773cfe4bf
commit
8dd8b8b438
@ -7,4 +7,5 @@
|
||||
}
|
||||
</select>
|
||||
<img src="{{hotel.imageUrl}}" alt="Hotel">
|
||||
<a *ngIf="!isDetail" routerLink="/hotels/{{hotel.id}}">Details</a>
|
||||
<app-star-rating [rating]="hotel.rating"></app-star-rating>
|
||||
|
@ -5,18 +5,21 @@ import { CurrencyPipe, NgIf } from "@angular/common";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
import { StarRatingComponent } from "../star-rating/star-rating.component";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { RouterLink } from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: 'app-hotel-item',
|
||||
standalone: true,
|
||||
templateUrl: './HotelItem.component.html',
|
||||
imports: [ChildComponent, CurrencyPipe, FormsModule, StarRatingComponent, NgIf],
|
||||
imports: [ChildComponent, CurrencyPipe, FormsModule, StarRatingComponent, NgIf, RouterLink],
|
||||
})
|
||||
export class HotelItem {
|
||||
|
||||
@Input() public hotel!: Hotel;
|
||||
public selectedLanguage?: string;
|
||||
|
||||
@Input() public isDetail: boolean = false;
|
||||
|
||||
public languageChange(lang: string) {
|
||||
this.selectedLanguage = lang;
|
||||
console.log(this.selectedLanguage);
|
||||
|
@ -51,7 +51,6 @@ export class HotelData implements InMemoryDbService {
|
||||
return { hotels };
|
||||
}
|
||||
|
||||
|
||||
genId(hotels: Hotel[]): number {
|
||||
return hotels.length > 0 ? Math.max(...hotels.map(hotel => hotel.id)) + 1 : 1;
|
||||
}
|
||||
|
@ -1,10 +1,4 @@
|
||||
<h1>{{'hello' | uppercase | text}}</h1>
|
||||
<app-search [(input)]="search"></app-search>
|
||||
@if (hotels[0].hotelName) {
|
||||
<div *ngFor="let hotel of hotels">
|
||||
<app-hotel-item *ngIf="hotel.hotelName.includes(search)" [hotel]="hotel"></app-hotel-item>
|
||||
</div>
|
||||
}
|
||||
<router-outlet></router-outlet>
|
||||
<!-- <p>ID: {{response.id}}</p> -->
|
||||
<!-- <p>userId: {{response.userId}}</p> -->
|
||||
<!-- <p>title: {{response.title}}</p> -->
|
||||
|
@ -8,70 +8,17 @@ import { inject } from '@angular/core';
|
||||
import { filter, from, last, map, Observable, scan } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Hotel } from './HotelItem/hotel';
|
||||
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
|
||||
@Injectable({providedIn: "root"})
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: true,
|
||||
imports: [NgFor, NgForOf, NgIf, HotelItem, SearchComponent, UpperCasePipe, TextPipe, AsyncPipe],
|
||||
imports: [RouterOutlet, NgFor, NgForOf, NgIf, HotelItem, SearchComponent, UpperCasePipe, TextPipe, AsyncPipe],
|
||||
templateUrl: './app.component.html',
|
||||
providers: [HotelService],
|
||||
styleUrl: './app.component.css'
|
||||
})
|
||||
export class AppComponent {
|
||||
public search: string = "";
|
||||
public hotelService: HotelService = inject(HotelService);
|
||||
public response: any = null;
|
||||
public hotels: Array<Hotel> = [{} as Hotel];
|
||||
|
||||
constructor (private http: HttpClient) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.http.get<Array<Hotel>>("api/hotels").subscribe(res => {
|
||||
this.hotels = res;
|
||||
});
|
||||
|
||||
const users = [
|
||||
{ name: "Max", age: 21 },
|
||||
{ name: "Peter", age: 31 },
|
||||
{ name: "Hans", age: 13 },
|
||||
{ name: "Klaus", age: 51 },
|
||||
{ name: "Dieter", age: 1 },
|
||||
{ name: "Jan-Marlon", age: 3 },
|
||||
]
|
||||
|
||||
const stream: Observable<User> = from(users);
|
||||
|
||||
stream.pipe(
|
||||
filter((user) => user.age > 18),
|
||||
scan((acc, user) => acc + user.age, 0),
|
||||
map((ageSum, index) => ageSum / (index + 1)),
|
||||
last(),
|
||||
).subscribe(console.log);
|
||||
|
||||
// const stream: Observable<number | string> = from([5, 1, 2, 12, 5, 14, 17, 5, "testing"]);
|
||||
|
||||
// stream.pipe(
|
||||
// filter((value) => typeof value === "number"),
|
||||
// tap((value) => console.log("Zahl:" + value)),
|
||||
// filter((value: number) => value % 2 === 0),
|
||||
// tap((value) => console.log("Gerade Zahl: " + value)),
|
||||
// toArray(),
|
||||
//).subscribe(console.log);
|
||||
}
|
||||
|
||||
public test() {
|
||||
console.log(this.search);
|
||||
}
|
||||
|
||||
// public foundHotels = this.hotels.pipe(
|
||||
// filter((hotel) => hotel.hotelName.includes(this.search)),
|
||||
// );
|
||||
}
|
||||
|
||||
|
@ -12,5 +12,9 @@ import { HotelData } from './api/api';
|
||||
registerLocaleData(localeDe, 'de-DE');
|
||||
registerLocaleData(localeCn, 'cn-CN');
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(), importProvidersFrom(InMemoryWebApiModule.forRoot(HotelData))]
|
||||
providers: [
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(routes),
|
||||
provideHttpClient(),
|
||||
importProvidersFrom(InMemoryWebApiModule.forRoot(HotelData))]
|
||||
};
|
||||
|
@ -1,3 +1,14 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { HotelDetailsComponent } from './hotel-details/hotel-details.component';
|
||||
import { HotelListComponent } from './hotel-list/hotel-list.component';
|
||||
|
||||
export const routes: Routes = [];
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: "",
|
||||
component: HotelListComponent,
|
||||
},
|
||||
{
|
||||
path: "hotels/:id",
|
||||
component: HotelDetailsComponent,
|
||||
},
|
||||
];
|
||||
|
0
src/app/hotel-details/hotel-details.component.css
Normal file
0
src/app/hotel-details/hotel-details.component.css
Normal file
1
src/app/hotel-details/hotel-details.component.html
Normal file
1
src/app/hotel-details/hotel-details.component.html
Normal file
@ -0,0 +1 @@
|
||||
<app-hotel-item [hotel]="hotel" [isDetail]="true"></app-hotel-item>
|
23
src/app/hotel-details/hotel-details.component.spec.ts
Normal file
23
src/app/hotel-details/hotel-details.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HotelDetailsComponent } from './hotel-details.component';
|
||||
|
||||
describe('HotelDetailsComponent', () => {
|
||||
let component: HotelDetailsComponent;
|
||||
let fixture: ComponentFixture<HotelDetailsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HotelDetailsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HotelDetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
29
src/app/hotel-details/hotel-details.component.ts
Normal file
29
src/app/hotel-details/hotel-details.component.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Hotel } from '../HotelItem/hotel';
|
||||
import { CurrencyPipe } from '@angular/common';
|
||||
import { StarRatingComponent } from '../star-rating/star-rating.component';
|
||||
import { HotelItem } from '../HotelItem/HotelItem.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hotel-details',
|
||||
standalone: true,
|
||||
imports: [CurrencyPipe, StarRatingComponent, HotelItem],
|
||||
templateUrl: './hotel-details.component.html',
|
||||
styleUrl: './hotel-details.component.css'
|
||||
})
|
||||
export class HotelDetailsComponent implements OnInit {
|
||||
public hotel: any;
|
||||
|
||||
constructor(private route: ActivatedRoute, private http: HttpClient) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
const routeParams = this.route.snapshot.paramMap;
|
||||
const hotelId = routeParams.get("id");
|
||||
|
||||
this.http.get<Hotel>("api/hotels/" + hotelId).subscribe(res => {
|
||||
this.hotel = res;
|
||||
});
|
||||
}
|
||||
}
|
0
src/app/hotel-list/hotel-list.component.css
Normal file
0
src/app/hotel-list/hotel-list.component.css
Normal file
7
src/app/hotel-list/hotel-list.component.html
Normal file
7
src/app/hotel-list/hotel-list.component.html
Normal file
@ -0,0 +1,7 @@
|
||||
<h1>{{'hello' | uppercase | text}}</h1>
|
||||
<app-search [(input)]="search"></app-search>
|
||||
@if (hotels[0].hotelName) {
|
||||
<div *ngFor="let hotel of hotels">
|
||||
<app-hotel-item *ngIf="hotel.hotelName.includes(search)" [hotel]="hotel"></app-hotel-item>
|
||||
</div>
|
||||
}
|
23
src/app/hotel-list/hotel-list.component.spec.ts
Normal file
23
src/app/hotel-list/hotel-list.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HotelListComponent } from './hotel-list.component';
|
||||
|
||||
describe('HotelListComponent', () => {
|
||||
let component: HotelListComponent;
|
||||
let fixture: ComponentFixture<HotelListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HotelListComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HotelListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
73
src/app/hotel-list/hotel-list.component.ts
Normal file
73
src/app/hotel-list/hotel-list.component.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import { CommonModule, NgFor, NgIf, UpperCasePipe } from '@angular/common';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { TextPipe } from '../../text.pipe';
|
||||
import { SearchComponent } from '../Search/search.component';
|
||||
import { HotelService } from '../Parent/services/hotel.service';
|
||||
import { Hotel } from '../HotelItem/hotel';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { filter, from, last, map, Observable, scan } from 'rxjs';
|
||||
import { HotelItem } from '../HotelItem/HotelItem.component';
|
||||
|
||||
interface User {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-hotel-list',
|
||||
standalone: true,
|
||||
imports: [UpperCasePipe, TextPipe, SearchComponent, HotelItem, NgFor, NgIf],
|
||||
templateUrl: './hotel-list.component.html',
|
||||
styleUrl: './hotel-list.component.css'
|
||||
})
|
||||
export class HotelListComponent {
|
||||
public search: string = "";
|
||||
public hotelService: HotelService = inject(HotelService);
|
||||
public response: any = null;
|
||||
public hotels: Array<Hotel> = [{} as Hotel];
|
||||
|
||||
constructor (private http: HttpClient) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.http.get<Array<Hotel>>("api/hotels").subscribe(res => {
|
||||
this.hotels = res;
|
||||
});
|
||||
|
||||
const users = [
|
||||
{ name: "Max", age: 21 },
|
||||
{ name: "Peter", age: 31 },
|
||||
{ name: "Hans", age: 13 },
|
||||
{ name: "Klaus", age: 51 },
|
||||
{ name: "Dieter", age: 1 },
|
||||
{ name: "Jan-Marlon", age: 3 },
|
||||
]
|
||||
|
||||
const stream: Observable<User> = from(users);
|
||||
|
||||
stream.pipe(
|
||||
filter((user) => user.age > 18),
|
||||
scan((acc, user) => acc + user.age, 0),
|
||||
map((ageSum, index) => ageSum / (index + 1)),
|
||||
last(),
|
||||
).subscribe(console.log);
|
||||
|
||||
// const stream: Observable<number | string> = from([5, 1, 2, 12, 5, 14, 17, 5, "testing"]);
|
||||
|
||||
// stream.pipe(
|
||||
// filter((value) => typeof value === "number"),
|
||||
// tap((value) => console.log("Zahl:" + value)),
|
||||
// filter((value: number) => value % 2 === 0),
|
||||
// tap((value) => console.log("Gerade Zahl: " + value)),
|
||||
// toArray(),
|
||||
//).subscribe(console.log);
|
||||
}
|
||||
|
||||
public test() {
|
||||
console.log(this.search);
|
||||
}
|
||||
|
||||
// public foundHotels = this.hotels.pipe(
|
||||
// filter((hotel) => hotel.hotelName.includes(this.search)),
|
||||
// );
|
||||
}
|
Loading…
Reference in New Issue
Block a user