ka
This commit is contained in:
parent
01de60aacb
commit
676aae14af
@ -1,7 +1,7 @@
|
|||||||
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 {EditHotelComponent} from "./hotel/edit-hotel.component";
|
import {CreateHotelComponent} from "./hotel/create-hotel.component";
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -11,7 +11,7 @@ export const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'hotels/new',
|
path: 'hotels/new',
|
||||||
component: EditHotelComponent,
|
component: CreateHotelComponent,
|
||||||
title: 'New Hotel'
|
title: 'New Hotel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
42
src/app/hotel/add-tag.component.ts
Normal file
42
src/app/hotel/add-tag.component.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {Component, Input} from "@angular/core";
|
||||||
|
import {NgForOf} from "@angular/common";
|
||||||
|
import {TagComponent} from "./tag.component";
|
||||||
|
import {
|
||||||
|
AbstractControl,
|
||||||
|
ControlContainer,
|
||||||
|
FormArray,
|
||||||
|
FormControl,
|
||||||
|
FormGroupDirective,
|
||||||
|
Validators
|
||||||
|
} from "@angular/forms";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-add-tag',
|
||||||
|
standalone: true,
|
||||||
|
template: `
|
||||||
|
`,
|
||||||
|
viewProviders: [
|
||||||
|
{
|
||||||
|
provide: ControlContainer,
|
||||||
|
useExisting: FormGroupDirective
|
||||||
|
}
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
NgForOf,
|
||||||
|
TagComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AddTagComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
form!: FormArray;
|
||||||
|
|
||||||
|
addTag() {
|
||||||
|
this.form.push(new FormControl('', [Validators.required]));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTag(id: AbstractControl) {
|
||||||
|
this.form.removeAt(this.form.controls.indexOf(id));
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,24 @@
|
|||||||
import {Component} from "@angular/core";
|
import {Component, inject} from "@angular/core";
|
||||||
import {Hotel} from "./hotel";
|
import {Hotel} from "./hotel";
|
||||||
import {HotelService} from "../service/hotel.service";
|
import {HotelService} from "../service/hotel.service";
|
||||||
|
import {EditHotelComponent} from "./edit-hotel.component";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-create-hotel",
|
selector: "app-create-hotel",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
EditHotelComponent
|
||||||
|
],
|
||||||
template: `
|
template: `
|
||||||
<app-create-hotel (updateHotel)="create($event)" />
|
<app-edit-hotel (updateHotel)="create($event)"></app-edit-hotel>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class CreateHotelComponent {
|
export class CreateHotelComponent {
|
||||||
|
|
||||||
protected hotelService: HotelService;
|
hotelService: HotelService = inject(HotelService);
|
||||||
|
|
||||||
create(hotel: Hotel) {
|
create(hotel: Hotel) {
|
||||||
console.log(hotel)
|
this.hotelService.createHotel(hotel).subscribe()
|
||||||
this.hotelService.createHotel(hotel).subscribe(console.log)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/app/hotel/delete-hotel.component.ts
Normal file
27
src/app/hotel/delete-hotel.component.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import {Component, inject, Input} from "@angular/core";
|
||||||
|
import {HotelService} from "../service/hotel.service";
|
||||||
|
import {Router} from "@angular/router";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-delete-hotel',
|
||||||
|
standalone: true,
|
||||||
|
template: `
|
||||||
|
<button (click)="delete()">Delete Hotel</button>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class DeleteHotelComponent {
|
||||||
|
@Input()
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
hotelService: HotelService = inject(HotelService);
|
||||||
|
|
||||||
|
router: Router = inject(Router);
|
||||||
|
|
||||||
|
delete() {
|
||||||
|
if (confirm('Are you sure?')) {
|
||||||
|
this.hotelService.deleteById(this.id).subscribe()
|
||||||
|
this.router.navigate(['/hotels']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,29 @@
|
|||||||
import {Component, EventEmitter, inject, Input, OnInit, Output} from '@angular/core';
|
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||||
import {
|
import {
|
||||||
AbstractControl,
|
AbstractControl,
|
||||||
|
FormArray,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
ValidationErrors, Validators
|
Validators
|
||||||
} from "@angular/forms";
|
} from "@angular/forms";
|
||||||
import {Hotel} from "./hotel";
|
import {Hotel} from "./hotel";
|
||||||
import {HotelService} from "../service/hotel.service";
|
|
||||||
import {RouterLink} from "@angular/router";
|
import {RouterLink} from "@angular/router";
|
||||||
import {HotelsComponent} from "./hotels.component";
|
import {AddTagComponent} from "./add-tag.component";
|
||||||
|
import {NgForOf} from "@angular/common";
|
||||||
|
import {TagComponent} from "./tag.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-create-hotel',
|
selector: 'app-edit-hotel',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
RouterLink
|
RouterLink,
|
||||||
|
AddTagComponent,
|
||||||
|
NgForOf,
|
||||||
|
TagComponent
|
||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
<ng-form [formGroup]="form" (ngSubmit)="submit()">
|
<ng-form [formGroup]="form" (ngSubmit)="submit()">
|
||||||
@ -39,6 +44,16 @@ import {HotelsComponent} from "./hotels.component";
|
|||||||
<input id="rating" type="number" formControlName="rating" min="0" max="5">
|
<input id="rating" type="number" formControlName="rating" min="0" max="5">
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
<button (click)="addTag()">+</button>
|
||||||
|
<div formArrayName="tags">
|
||||||
|
@for (tag of getTags().controls; track null) {
|
||||||
|
<br>
|
||||||
|
<input type="text" placeholder="tag" value="{{tag.value}}" formControlName="tagsControl">
|
||||||
|
<button (click)="deleteTag(tag)">-</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
<button type="submit" (click)="submit()">Submit</button>
|
<button type="submit" (click)="submit()">Submit</button>
|
||||||
</ng-form>
|
</ng-form>
|
||||||
|
|
||||||
@ -55,11 +70,18 @@ export class EditHotelComponent implements OnInit {
|
|||||||
form!: FormGroup
|
form!: FormGroup
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
const tags = [];
|
||||||
|
|
||||||
|
for (const tag of this.hotel?.tags ?? []) {
|
||||||
|
tags.push(new FormControl(tag, [Validators.required]));
|
||||||
|
}
|
||||||
|
|
||||||
this.form = new FormGroup({
|
this.form = new FormGroup({
|
||||||
name: new FormControl(this.hotel?.hotelName, [Validators.required]),
|
name: new FormControl(this.hotel?.hotelName, [Validators.required]),
|
||||||
description: new FormControl(this.hotel?.description, [Validators.required]),
|
description: new FormControl(this.hotel?.description, [Validators.required]),
|
||||||
price: new FormControl(this.hotel?.price, [Validators.required]),
|
price: new FormControl(this.hotel?.price, [Validators.required]),
|
||||||
rating: new FormControl(this.hotel?.rating, [Validators.required, Validators.min(0), Validators.max(5)]),
|
rating: new FormControl(this.hotel?.rating, [Validators.required, Validators.min(0), Validators.max(5)]),
|
||||||
|
tags: new FormArray(tags),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +89,6 @@ export class EditHotelComponent implements OnInit {
|
|||||||
if (!this.form.valid) {
|
if (!this.form.valid) {
|
||||||
console.error('Form invalid');
|
console.error('Form invalid');
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hotel: Hotel = {
|
const hotel: Hotel = {
|
||||||
@ -77,10 +98,23 @@ export class EditHotelComponent implements OnInit {
|
|||||||
price: this.form.value.price,
|
price: this.form.value.price,
|
||||||
rating: this.form.value.rating,
|
rating: this.form.value.rating,
|
||||||
id: this.hotel?.id ?? 0,
|
id: this.hotel?.id ?? 0,
|
||||||
|
tags: this.form.value.tags ?? []
|
||||||
};
|
};
|
||||||
|
console.log(hotel)
|
||||||
this.updateHotel.emit(hotel)
|
this.updateHotel.emit(hotel)
|
||||||
|
|
||||||
this.hotel = hotel;
|
this.hotel = hotel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTags() {
|
||||||
|
return this.form.controls['tags'] as FormArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag() {
|
||||||
|
this.getTags().push(new FormControl('', [Validators.required]));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTag(tagElement: AbstractControl) {
|
||||||
|
this.getTags().removeAt(this.getTags().controls.indexOf(tagElement));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import {ActivatedRoute} from "@angular/router";
|
|||||||
import {HotelService} from "../service/hotel.service";
|
import {HotelService} from "../service/hotel.service";
|
||||||
import {catchError, EMPTY} from "rxjs";
|
import {catchError, EMPTY} from "rxjs";
|
||||||
import {EditHotelComponent} from "./edit-hotel.component";
|
import {EditHotelComponent} from "./edit-hotel.component";
|
||||||
|
import {DeleteHotelComponent} from "./delete-hotel.component";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -16,12 +17,14 @@ import {EditHotelComponent} from "./edit-hotel.component";
|
|||||||
CurrencyPipe,
|
CurrencyPipe,
|
||||||
StarComponent,
|
StarComponent,
|
||||||
NgOptimizedImage,
|
NgOptimizedImage,
|
||||||
EditHotelComponent
|
EditHotelComponent,
|
||||||
|
DeleteHotelComponent
|
||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
<div style="border: white 2px; border-radius: 2px">
|
<div style="border: white 2px; border-radius: 2px">
|
||||||
@if (hotel && !alert) {
|
@if (hotel && !alert) {
|
||||||
<app-create-hotel [hotel]="hotel" (updateHotel)="update($event)" />
|
<app-edit-hotel [hotel]="hotel" (updateHotel)="update($event)" />
|
||||||
|
<app-delete-hotel [id]="hotel.id" />
|
||||||
} @else if(alert) {
|
} @else if(alert) {
|
||||||
<h2>{{alert}}</h2>
|
<h2>{{alert}}</h2>
|
||||||
} @else {
|
} @else {
|
||||||
|
@ -5,4 +5,5 @@ export interface Hotel {
|
|||||||
price: number;
|
price: number;
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
rating: number;
|
rating: number;
|
||||||
|
tags: string[];
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import {StarComponent} from "../star/star.component";
|
|||||||
<form>
|
<form>
|
||||||
<input name="search" [ngModel]="search" (ngModelChange)="searchEvent($event)">
|
<input name="search" [ngModel]="search" (ngModelChange)="searchEvent($event)">
|
||||||
</form>
|
</form>
|
||||||
|
<p routerLink="/hotels/new">Create Hotel</p>
|
||||||
@for (hotel of (matchingHotels | async); track hotel.id) {
|
@for (hotel of (matchingHotels | async); track hotel.id) {
|
||||||
<div>{{hotel.hotelName}}</div>
|
<div>{{hotel.hotelName}}</div>
|
||||||
<img src="{{hotel.imageUrl}}" alt="{{hotel.hotelName}}" height="64" width="64">
|
<img src="{{hotel.imageUrl}}" alt="{{hotel.hotelName}}" height="64" width="64">
|
||||||
|
33
src/app/hotel/tag.component.ts
Normal file
33
src/app/hotel/tag.component.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import {Component, EventEmitter, Input, Output} from "@angular/core";
|
||||||
|
import {AbstractControl, ControlContainer, FormGroupDirective, ReactiveFormsModule} from "@angular/forms";
|
||||||
|
import {JsonPipe} from "@angular/common";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
selector: 'app-tag',
|
||||||
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
JsonPipe
|
||||||
|
],
|
||||||
|
viewProviders: [
|
||||||
|
{
|
||||||
|
provide: ControlContainer,
|
||||||
|
useExisting: FormGroupDirective
|
||||||
|
}
|
||||||
|
],
|
||||||
|
template: `
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class TagComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
tagElement!: AbstractControl;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
deleteEvent: EventEmitter<AbstractControl> = new EventEmitter();
|
||||||
|
|
||||||
|
delete() {
|
||||||
|
this.deleteEvent.emit(this.tagElement);
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,8 @@ export class HotelDataService implements InMemoryDbService{
|
|||||||
"description": "Schöne Aussicht am Meer",
|
"description": "Schöne Aussicht am Meer",
|
||||||
"price": 230.5,
|
"price": 230.5,
|
||||||
"imageUrl": "assets/img/heisenberg.jpg",
|
"imageUrl": "assets/img/heisenberg.jpg",
|
||||||
"rating": 3.5
|
"rating": 3.5,
|
||||||
|
"tags": ["Meer", "Berge"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
@ -19,7 +20,8 @@ export class HotelDataService implements InMemoryDbService{
|
|||||||
"description": "Genießen Sie den Blick auf die Berge",
|
"description": "Genießen Sie den Blick auf die Berge",
|
||||||
"price": 145.5,
|
"price": 145.5,
|
||||||
"imageUrl": "assets/img/kjan.png",
|
"imageUrl": "assets/img/kjan.png",
|
||||||
"rating": 5
|
"rating": 5,
|
||||||
|
"tags": ["Meer", "Berge"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
@ -27,7 +29,8 @@ export class HotelDataService implements InMemoryDbService{
|
|||||||
"description": "Kompletter Aufenthalt mit Autoservice",
|
"description": "Kompletter Aufenthalt mit Autoservice",
|
||||||
"price": 120.12,
|
"price": 120.12,
|
||||||
"imageUrl": "assets/img/huy.png",
|
"imageUrl": "assets/img/huy.png",
|
||||||
"rating": 4
|
"rating": 4,
|
||||||
|
"tags": ["Meer", "Berge"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 4,
|
"id": 4,
|
||||||
@ -35,7 +38,8 @@ export class HotelDataService implements InMemoryDbService{
|
|||||||
"description": "Wunderschönes Ambiente für Ihren Aufenthalt",
|
"description": "Wunderschönes Ambiente für Ihren Aufenthalt",
|
||||||
"price": 135.12,
|
"price": 135.12,
|
||||||
"imageUrl": "assets/img/rat.png",
|
"imageUrl": "assets/img/rat.png",
|
||||||
"rating": 2.5
|
"rating": 2.5,
|
||||||
|
"tags": ["Meer", "Berge"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -24,4 +24,8 @@ export class HotelService {
|
|||||||
public createHotel(hotel: Hotel): Observable<Hotel> {
|
public createHotel(hotel: Hotel): Observable<Hotel> {
|
||||||
return this.httpClient.post<Hotel>(`/api/hotels`, hotel)
|
return this.httpClient.post<Hotel>(`/api/hotels`, hotel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public deleteById(id: number): Observable<Hotel> {
|
||||||
|
return this.httpClient.delete<Hotel>(`/api/hotels/${id}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user