prettier
This commit is contained in:
parent
59e90dc534
commit
9ab7a128f3
@ -1,5 +1,4 @@
|
||||
import {ErrorHandler as NgErrorHandler} from "@angular/core";
|
||||
|
||||
import { ErrorHandler as NgErrorHandler } from '@angular/core';
|
||||
|
||||
export class ErrorHandler implements NgErrorHandler {
|
||||
handleError(error: any): void {
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -24,6 +24,8 @@ describe('AppComponent', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, hotel-manager');
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Hello, hotel-manager',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,16 +1,12 @@
|
||||
import {Component, inject, OnInit} from '@angular/core';
|
||||
import {filter, from, map, reduce} from "rxjs";
|
||||
import {Router, RouterOutlet} from "@angular/router";
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { filter, from, map, reduce } from 'rxjs';
|
||||
import { Router, RouterOutlet } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterOutlet
|
||||
],
|
||||
template: `
|
||||
<router-outlet />
|
||||
`
|
||||
imports: [RouterOutlet],
|
||||
template: ` <router-outlet /> `,
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
router: Router = inject(Router);
|
||||
@ -58,17 +54,24 @@ export class AppComponent implements OnInit {
|
||||
{
|
||||
name: 'Victor',
|
||||
age: 39,
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
from(users).pipe(
|
||||
filter(user => user.age >= 18),
|
||||
reduce((acc, user) => {
|
||||
acc.age += user.age
|
||||
from(users)
|
||||
.pipe(
|
||||
filter((user) => user.age >= 18),
|
||||
reduce(
|
||||
(acc, user) => {
|
||||
acc.age += user.age;
|
||||
acc.count++;
|
||||
return acc;
|
||||
}, {age: 0, count: 0}),
|
||||
map(data => data.age / data.count),
|
||||
).subscribe((data) => {console.log("avg age: ", data)});
|
||||
},
|
||||
{ age: 0, count: 0 },
|
||||
),
|
||||
map((data) => data.age / data.count),
|
||||
)
|
||||
.subscribe((data) => {
|
||||
console.log('avg age: ', data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,23 @@
|
||||
import {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core';
|
||||
import {
|
||||
ApplicationConfig,
|
||||
importProvidersFrom,
|
||||
provideZoneChangeDetection,
|
||||
} from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { routes } from './app.routes';
|
||||
import {registerLocaleData} from "@angular/common";
|
||||
import localeDe from "@angular/common/locales/de"
|
||||
import localeCn from "@angular/common/locales/en"
|
||||
import localeJap from "@angular/common/locales/en"
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {InMemoryWebApiModule} from "angular-in-memory-web-api";
|
||||
import {HotelDataService} from "./hotel/service/HotelData.service";
|
||||
import {ErrorHandler} from "./ErrorHandler";
|
||||
import {ErrorHandler as NgErrorHandler} from "@angular/core";
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeCn from '@angular/common/locales/en';
|
||||
import localeJap from '@angular/common/locales/en';
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
|
||||
import { HotelDataService } from './hotel/service/HotelData.service';
|
||||
import { ErrorHandler } from './ErrorHandler';
|
||||
import { ErrorHandler as NgErrorHandler } from '@angular/core';
|
||||
|
||||
registerLocaleData(localeDe, 'de-DE')
|
||||
registerLocaleData(localeCn, 'cn-CN')
|
||||
registerLocaleData(localeJap, 'ja-JP')
|
||||
registerLocaleData(localeDe, 'de-DE');
|
||||
registerLocaleData(localeCn, 'cn-CN');
|
||||
registerLocaleData(localeJap, 'ja-JP');
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
@ -22,7 +26,7 @@ export const appConfig: ApplicationConfig = {
|
||||
importProvidersFrom(InMemoryWebApiModule.forRoot(HotelDataService)),
|
||||
{
|
||||
provide: NgErrorHandler,
|
||||
useClass: ErrorHandler
|
||||
}
|
||||
]
|
||||
useClass: ErrorHandler,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Routes} from '@angular/router';
|
||||
import {HotelsComponent} from "./hotel/component/hotels.component";
|
||||
import {HotelComponent} from "./hotel/component/hotel.component";
|
||||
import {CreateHotelComponent} from "./hotel/component/create-hotel.component";
|
||||
import { Routes } from '@angular/router';
|
||||
import { HotelsComponent } from './hotel/component/hotels.component';
|
||||
import { HotelComponent } from './hotel/component/hotel.component';
|
||||
import { CreateHotelComponent } from './hotel/component/create-hotel.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
@ -12,11 +12,11 @@ export const routes: Routes = [
|
||||
{
|
||||
path: 'hotels/new',
|
||||
component: CreateHotelComponent,
|
||||
title: 'New Hotel'
|
||||
title: 'New Hotel',
|
||||
},
|
||||
{
|
||||
path: 'hotels/:hotelId',
|
||||
component: HotelComponent,
|
||||
title: 'Hotel',
|
||||
}
|
||||
},
|
||||
];
|
||||
|
@ -1,25 +1,20 @@
|
||||
import {Component, EventEmitter, Output} from "@angular/core";
|
||||
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
|
||||
import {Lang} from "./lang";
|
||||
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Lang } from './lang';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: "app-currency",
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
FormsModule
|
||||
],
|
||||
selector: 'app-currency',
|
||||
imports: [ReactiveFormsModule, FormsModule],
|
||||
template: `
|
||||
<select [ngModel]="currency" (ngModelChange)="setCurrency($event)">
|
||||
@for (currency of currencies; track currency.code) {
|
||||
<option value="{{currency.name}}">{{ currency.name }}</option>
|
||||
<option value="{{ currency.name }}">{{ currency.name }}</option>
|
||||
}
|
||||
</select>
|
||||
`
|
||||
`,
|
||||
})
|
||||
export class CurrencyComponent {
|
||||
|
||||
@Output()
|
||||
public currency: EventEmitter<Lang> = new EventEmitter();
|
||||
|
||||
@ -27,24 +22,24 @@ export class CurrencyComponent {
|
||||
{
|
||||
name: 'de',
|
||||
code: 'de-DE',
|
||||
currency: 'EUR'
|
||||
currency: 'EUR',
|
||||
},
|
||||
{
|
||||
name: 'en',
|
||||
code: 'en-US',
|
||||
currency: 'USD'
|
||||
currency: 'USD',
|
||||
},
|
||||
{
|
||||
name: 'jap',
|
||||
code: 'ja-JP',
|
||||
currency: 'JPY'
|
||||
currency: 'JPY',
|
||||
},
|
||||
{
|
||||
name: 'cn',
|
||||
code: 'cn-CN',
|
||||
currency: 'CNY'
|
||||
}
|
||||
]
|
||||
currency: 'CNY',
|
||||
},
|
||||
];
|
||||
|
||||
public setCurrency(currencyInput: string): void {
|
||||
for (const currency of this.currencies) {
|
||||
|
@ -1,22 +1,18 @@
|
||||
import {Component, inject} from "@angular/core";
|
||||
import {Hotel} from "../model/hotel";
|
||||
import {HotelService} from "../service/hotel.service";
|
||||
import {EditHotelComponent} from "./edit-hotel.component";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Hotel } from '../model/hotel';
|
||||
import { HotelService } from '../service/hotel.service';
|
||||
import { EditHotelComponent } from './edit-hotel.component';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: "app-create-hotel",
|
||||
selector: 'app-create-hotel',
|
||||
standalone: true,
|
||||
imports: [
|
||||
EditHotelComponent
|
||||
],
|
||||
imports: [EditHotelComponent],
|
||||
template: `
|
||||
<app-edit-hotel (updateHotel)="create($event)"></app-edit-hotel>
|
||||
`
|
||||
`,
|
||||
})
|
||||
export class CreateHotelComponent {
|
||||
|
||||
hotelService: HotelService = inject(HotelService);
|
||||
|
||||
router: Router = inject(Router);
|
||||
|
@ -1,14 +1,11 @@
|
||||
import {Component, inject, Input} from "@angular/core";
|
||||
import {HotelService} from "../service/hotel.service";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
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>
|
||||
`
|
||||
template: ` <button (click)="delete()">Delete Hotel</button> `,
|
||||
})
|
||||
export class DeleteHotelComponent {
|
||||
@Input()
|
||||
@ -20,7 +17,7 @@ export class DeleteHotelComponent {
|
||||
|
||||
delete() {
|
||||
if (confirm('Are you sure?')) {
|
||||
this.hotelService.deleteById(this.id).subscribe()
|
||||
this.hotelService.deleteById(this.id).subscribe();
|
||||
this.router.navigate(['/hotels']);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,11 @@
|
||||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnInit,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
AbstractControl,
|
||||
FormArray,
|
||||
@ -7,13 +14,13 @@ import {
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
ValidationErrors,
|
||||
Validators
|
||||
} from "@angular/forms";
|
||||
import {Hotel} from "../model/hotel";
|
||||
import {RouterLink} from "@angular/router";
|
||||
import {NgForOf, NgIf} from "@angular/common";
|
||||
import {debounceTime} from "rxjs";
|
||||
import {ErrorMsgComponent} from "./error-msg.component";
|
||||
Validators,
|
||||
} from '@angular/forms';
|
||||
import { Hotel } from '../model/hotel';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { debounceTime } from 'rxjs';
|
||||
import { ErrorMsgComponent } from './error-msg.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-hotel',
|
||||
@ -29,83 +36,101 @@ import {ErrorMsgComponent} from "./error-msg.component";
|
||||
template: `
|
||||
<ng-form [formGroup]="form" (ngSubmit)="submit()">
|
||||
<label for="name">Name</label>
|
||||
<br>
|
||||
<input id="name" type="text" formControlName="name">
|
||||
<app-error-msg [msg]="errorMsgs['name']"/>
|
||||
<br>
|
||||
<br />
|
||||
<input id="name" type="text" formControlName="name" />
|
||||
<app-error-msg [msg]="errorMsgs['name']" />
|
||||
<br />
|
||||
<label for="description">Description</label>
|
||||
<br>
|
||||
<input id="description" type="text" formControlName="description">
|
||||
<app-error-msg [msg]="errorMsgs['description']"/>
|
||||
<br>
|
||||
<br />
|
||||
<input id="description" type="text" formControlName="description" />
|
||||
<app-error-msg [msg]="errorMsgs['description']" />
|
||||
<br />
|
||||
<label for="price">Price</label>
|
||||
<br>
|
||||
<input id="price" type="number" formControlName="price">
|
||||
<app-error-msg [msg]="errorMsgs['price']"/>
|
||||
<br>
|
||||
<br />
|
||||
<input id="price" type="number" formControlName="price" />
|
||||
<app-error-msg [msg]="errorMsgs['price']" />
|
||||
<br />
|
||||
<label for="rating">Rating</label>
|
||||
<br>
|
||||
<input id="rating" type="number" formControlName="rating">
|
||||
<app-error-msg [msg]="errorMsgs['rating']"/>
|
||||
<br>
|
||||
<br>
|
||||
<br />
|
||||
<input id="rating" type="number" formControlName="rating" />
|
||||
<app-error-msg [msg]="errorMsgs['rating']" />
|
||||
<br />
|
||||
<br />
|
||||
<label for="email">Email</label>
|
||||
<input id="email" type="checkbox" name="contactType" value="Email" [checked]="activeContact == 'email'"
|
||||
(click)="changeContactType('email')">
|
||||
<br>
|
||||
<input
|
||||
id="email"
|
||||
type="checkbox"
|
||||
name="contactType"
|
||||
value="Email"
|
||||
[checked]="activeContact == 'email'"
|
||||
(click)="changeContactType('email')"
|
||||
/>
|
||||
<br />
|
||||
<label for="phoneNumber">Phone Number</label>
|
||||
<input id="phoneNumber" type="checkbox" name="contactType" value="PhoneNumber"
|
||||
[checked]="activeContact == 'phoneNumber'" (click)="changeContactType('phoneNumber')">
|
||||
<br>
|
||||
<input
|
||||
id="phoneNumber"
|
||||
type="checkbox"
|
||||
name="contactType"
|
||||
value="PhoneNumber"
|
||||
[checked]="activeContact == 'phoneNumber'"
|
||||
(click)="changeContactType('phoneNumber')"
|
||||
/>
|
||||
<br />
|
||||
<label for="none">None</label>
|
||||
<input id="none" type="checkbox" name="contactType" value="none" [checked]="activeContact == 'none'"
|
||||
(click)="changeContactType('none')">
|
||||
<input
|
||||
id="none"
|
||||
type="checkbox"
|
||||
name="contactType"
|
||||
value="none"
|
||||
[checked]="activeContact == 'none'"
|
||||
(click)="changeContactType('none')"
|
||||
/>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
@if (activeContact === 'email') {
|
||||
<app-error-msg [msg]="errorMsgs['emailGroup']"/>
|
||||
<app-error-msg [msg]="errorMsgs['emailGroup']" />
|
||||
<div formGroupName="emailGroup">
|
||||
<app-error-msg [msg]="errorMsgs['email']"/>
|
||||
<br>
|
||||
<app-error-msg [msg]="errorMsgs['email']" />
|
||||
<br />
|
||||
<label for="email">Email</label>
|
||||
<br>
|
||||
<input type="email" formControlName="email" required>
|
||||
<br>
|
||||
<br />
|
||||
<input type="email" formControlName="email" required />
|
||||
<br />
|
||||
<label for="emailConfirm">Confirm Email</label>
|
||||
<app-error-msg [msg]="errorMsgs['emailConfirm']"/>
|
||||
<br>
|
||||
<input type="email" formControlName="emailConfirm" required>
|
||||
<app-error-msg [msg]="errorMsgs['emailConfirm']" />
|
||||
<br />
|
||||
<input type="email" formControlName="emailConfirm" required />
|
||||
</div>
|
||||
} @else if (activeContact === 'phoneNumber') {
|
||||
<app-error-msg [msg]="errorMsgs['phoneNumberGroup']"/>
|
||||
<app-error-msg [msg]="errorMsgs['phoneNumberGroup']" />
|
||||
<div formGroupName="phoneNumberGroup">
|
||||
<app-error-msg [msg]="errorMsgs['phoneNumber']"/>
|
||||
<br>
|
||||
<app-error-msg [msg]="errorMsgs['phoneNumber']" />
|
||||
<br />
|
||||
<label for="phoneNumber">Phone Number</label>
|
||||
<br>
|
||||
<input type="number" formControlName="phoneNumber" required>
|
||||
<br>
|
||||
<br />
|
||||
<input type="number" formControlName="phoneNumber" required />
|
||||
<br />
|
||||
<label for="phoneNumberConfirm">Confirm Phone Number</label>
|
||||
<app-error-msg [msg]="errorMsgs['phoneNumberConfirm']"/>
|
||||
<br>
|
||||
<input type="number" formControlName="phoneNumberConfirm" required>
|
||||
<app-error-msg [msg]="errorMsgs['phoneNumberConfirm']" />
|
||||
<br />
|
||||
<input type="number" formControlName="phoneNumberConfirm" required />
|
||||
</div>
|
||||
}
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br />
|
||||
<br />
|
||||
<button (click)="addTag()">+</button>
|
||||
<div formArrayName="tags">
|
||||
<div *ngFor="let tag of getTags().controls; let i = index">
|
||||
<input type="text" placeholder="tag" [formControlName]="i">
|
||||
<input type="text" placeholder="tag" [formControlName]="i" />
|
||||
<button (click)="deleteTag(tag)">-</button>
|
||||
</div>
|
||||
<app-error-msg [msg]="errorMsgs['tags']"/>
|
||||
<app-error-msg [msg]="errorMsgs['tags']" />
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<br />
|
||||
<br />
|
||||
<button type="submit" (click)="submit()">Submit</button>
|
||||
</ng-form>
|
||||
|
||||
@ -119,9 +144,9 @@ export class EditHotelComponent implements OnInit {
|
||||
hotel: Hotel | null = null;
|
||||
|
||||
@Output()
|
||||
updateHotel: EventEmitter<Hotel> = new EventEmitter
|
||||
updateHotel: EventEmitter<Hotel> = new EventEmitter();
|
||||
|
||||
form!: FormGroup
|
||||
form!: FormGroup;
|
||||
|
||||
validationErrors: Record<string, string> = {
|
||||
required: 'This field is required',
|
||||
@ -154,13 +179,19 @@ export class EditHotelComponent implements OnInit {
|
||||
|
||||
this.form = new FormGroup({
|
||||
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]),
|
||||
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),
|
||||
});
|
||||
|
||||
this.initGroups()
|
||||
this.initGroups();
|
||||
|
||||
if (this.hotel?.email) {
|
||||
this.form.addControl('emailGroup', this.emailGroup);
|
||||
@ -168,7 +199,7 @@ export class EditHotelComponent implements OnInit {
|
||||
this.form.addControl('phoneNumberGroup', this.phoneNumberGroup);
|
||||
}
|
||||
|
||||
Object.keys(this.form.controls).forEach(controlName => {
|
||||
Object.keys(this.form.controls).forEach((controlName) => {
|
||||
let debounce = 1000;
|
||||
const control = this.form.get(controlName);
|
||||
if (!control) {
|
||||
@ -180,7 +211,7 @@ export class EditHotelComponent implements OnInit {
|
||||
}
|
||||
|
||||
control?.valueChanges?.pipe(debounceTime(debounce)).subscribe(() => {
|
||||
this.setErrorMessage(controlName, control)
|
||||
this.setErrorMessage(controlName, control);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -192,7 +223,7 @@ export class EditHotelComponent implements OnInit {
|
||||
}
|
||||
|
||||
const hotel: Hotel = {
|
||||
imageUrl: this.hotel?.imageUrl ?? "",
|
||||
imageUrl: this.hotel?.imageUrl ?? '',
|
||||
hotelName: this.form.value.name,
|
||||
description: this.form.value.description,
|
||||
price: this.form.value.price,
|
||||
@ -200,10 +231,10 @@ export class EditHotelComponent implements OnInit {
|
||||
id: this.hotel?.id ?? 0,
|
||||
tags: this.form.value.tags ?? [],
|
||||
email: this.form.value.email,
|
||||
phoneNumber: this.form.value.phoneNumber
|
||||
phoneNumber: this.form.value.phoneNumber,
|
||||
};
|
||||
|
||||
this.updateHotel.emit(hotel)
|
||||
this.updateHotel.emit(hotel);
|
||||
|
||||
this.hotel = hotel;
|
||||
}
|
||||
@ -221,11 +252,13 @@ export class EditHotelComponent implements OnInit {
|
||||
}
|
||||
|
||||
setErrorMessage(controlName: string, control: AbstractControl) {
|
||||
this.errorMsgs[controlName] = Object.keys(control.errors ?? {}).map((key) => this.validationErrors[key]).join(' ');
|
||||
this.errorMsgs[controlName] = Object.keys(control.errors ?? {})
|
||||
.map((key) => this.validationErrors[key])
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
showErrors() {
|
||||
Object.keys(this.form.controls).forEach(controlName => {
|
||||
Object.keys(this.form.controls).forEach((controlName) => {
|
||||
const control = this.form.get(controlName);
|
||||
if (!control) {
|
||||
return;
|
||||
@ -254,7 +287,7 @@ export class EditHotelComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (email.value !== emailConfirm.value) {
|
||||
return {emailMatch: true};
|
||||
return { emailMatch: true };
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -269,21 +302,41 @@ export class EditHotelComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (phoneNumber.value !== phoneNumberConfirm.value) {
|
||||
return {phoneNumberMatch: true};
|
||||
return { phoneNumberMatch: true };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private initGroups() {
|
||||
this.emailGroup = new FormGroup({
|
||||
email: new FormControl(this.hotel?.email, [Validators.required, Validators.email]),
|
||||
emailConfirm: new FormControl(this.hotel?.email, [Validators.required, Validators.email]),
|
||||
}, {validators: this.emailMatch});
|
||||
this.emailGroup = new FormGroup(
|
||||
{
|
||||
email: new FormControl(this.hotel?.email, [
|
||||
Validators.required,
|
||||
Validators.email,
|
||||
]),
|
||||
emailConfirm: new FormControl(this.hotel?.email, [
|
||||
Validators.required,
|
||||
Validators.email,
|
||||
]),
|
||||
},
|
||||
{ validators: this.emailMatch },
|
||||
);
|
||||
|
||||
this.phoneNumberGroup = new FormGroup({
|
||||
phoneNumber: new FormControl(this.hotel?.phoneNumber, [Validators.required, Validators.maxLength(10), Validators.minLength(10)]),
|
||||
phoneNumberConfirm: new FormControl(this.hotel?.phoneNumber, [Validators.required, Validators.maxLength(10), Validators.minLength(10)]),
|
||||
}, {validators: this.phoneNumberMatch});
|
||||
this.phoneNumberGroup = new FormGroup(
|
||||
{
|
||||
phoneNumber: new FormControl(this.hotel?.phoneNumber, [
|
||||
Validators.required,
|
||||
Validators.maxLength(10),
|
||||
Validators.minLength(10),
|
||||
]),
|
||||
phoneNumberConfirm: new FormControl(this.hotel?.phoneNumber, [
|
||||
Validators.required,
|
||||
Validators.maxLength(10),
|
||||
Validators.minLength(10),
|
||||
]),
|
||||
},
|
||||
{ validators: this.phoneNumberMatch },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
import {Component, Input} from "@angular/core";
|
||||
import {NgIf} from "@angular/common";
|
||||
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-error-msg',
|
||||
imports: [
|
||||
NgIf
|
||||
],
|
||||
imports: [NgIf],
|
||||
template: `
|
||||
<div *ngIf="msg" class="alert alert-danger border">
|
||||
{{ msg }}
|
||||
@ -38,7 +35,7 @@ import {NgIf} from "@angular/common";
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
`
|
||||
`,
|
||||
})
|
||||
export class ErrorMsgComponent {
|
||||
@Input()
|
||||
|
@ -1,13 +1,12 @@
|
||||
import {Component, inject, OnInit} from "@angular/core";
|
||||
import {Hotel} from "../model/hotel"
|
||||
import {CurrencyPipe, NgOptimizedImage} from "@angular/common";
|
||||
import {StarComponent} from "./star.component";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {HotelService} from "../service/hotel.service";
|
||||
import {catchError, EMPTY} from "rxjs";
|
||||
import {EditHotelComponent} from "./edit-hotel.component";
|
||||
import {DeleteHotelComponent} from "./delete-hotel.component";
|
||||
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { Hotel } from '../model/hotel';
|
||||
import { CurrencyPipe, NgOptimizedImage } from '@angular/common';
|
||||
import { StarComponent } from './star.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { HotelService } from '../service/hotel.service';
|
||||
import { catchError, EMPTY } from 'rxjs';
|
||||
import { EditHotelComponent } from './edit-hotel.component';
|
||||
import { DeleteHotelComponent } from './delete-hotel.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@ -17,26 +16,25 @@ import {DeleteHotelComponent} from "./delete-hotel.component";
|
||||
StarComponent,
|
||||
NgOptimizedImage,
|
||||
EditHotelComponent,
|
||||
DeleteHotelComponent
|
||||
DeleteHotelComponent,
|
||||
],
|
||||
template: `
|
||||
<div style="border: white 2px; border-radius: 2px">
|
||||
@if (hotel && !alert) {
|
||||
<app-edit-hotel [hotel]="hotel" (updateHotel)="update($event)" />
|
||||
<app-delete-hotel [id]="hotel.id" />
|
||||
} @else if(alert) {
|
||||
<h2>{{alert}}</h2>
|
||||
} @else if (alert) {
|
||||
<h2>{{ alert }}</h2>
|
||||
} @else {
|
||||
<h2>loading</h2>
|
||||
}
|
||||
|
||||
</div>
|
||||
`
|
||||
`,
|
||||
})
|
||||
export class HotelComponent implements OnInit {
|
||||
protected hotel!: Hotel;
|
||||
|
||||
protected alert: string|undefined
|
||||
protected alert: string | undefined;
|
||||
|
||||
private route: ActivatedRoute = inject(ActivatedRoute);
|
||||
|
||||
@ -44,15 +42,22 @@ export class HotelComponent implements OnInit {
|
||||
|
||||
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}`
|
||||
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}})
|
||||
}),
|
||||
)
|
||||
.subscribe({
|
||||
next: (hotel: Hotel) => {
|
||||
this.hotel = hotel;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
update(hotel: Hotel): void {
|
||||
this.hotelService.updateHotelById(hotel).subscribe()
|
||||
this.hotelService.updateHotelById(hotel).subscribe();
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +1,67 @@
|
||||
import {ChangeDetectionStrategy, Component, inject} from "@angular/core";
|
||||
import {HotelComponent} from "./hotel.component";
|
||||
import {Hotel} from "../model/hotel";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {Lang} from "../../currency/lang";
|
||||
import {HotelService} from "../service/hotel.service";
|
||||
import {Observable} from "rxjs";
|
||||
import {AsyncPipe, NgIf} from "@angular/common";
|
||||
import {CurrencyComponent} from "../../currency/currency.component";
|
||||
import {RouterLink} from "@angular/router";
|
||||
import {StarComponent} from "./star.component";
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { HotelComponent } from './hotel.component';
|
||||
import { Hotel } from '../model/hotel';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Lang } from '../../currency/lang';
|
||||
import { HotelService } from '../service/hotel.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AsyncPipe, NgIf } from '@angular/common';
|
||||
import { CurrencyComponent } from '../../currency/currency.component';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { StarComponent } from './star.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
template: `
|
||||
<app-currency (currency)="currency = $event"></app-currency>
|
||||
<form>
|
||||
<input name="search" [ngModel]="search" (ngModelChange)="searchEvent($event)">
|
||||
<input
|
||||
name="search"
|
||||
[ngModel]="search"
|
||||
(ngModelChange)="searchEvent($event)"
|
||||
/>
|
||||
</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 *ngIf="hotel.hotelName.toLowerCase().includes(search)">
|
||||
<div>{{ hotel.hotelName }}</div>
|
||||
<img src="{{hotel.imageUrl}}" alt="{{hotel.hotelName}}" height="64" width="64">
|
||||
<br>
|
||||
<button routerLink="{{hotel.id}}">Details</button>
|
||||
<hr>
|
||||
<img
|
||||
src="{{ hotel.imageUrl }}"
|
||||
alt="{{ hotel.hotelName }}"
|
||||
height="64"
|
||||
width="64"
|
||||
/>
|
||||
<br />
|
||||
<button routerLink="{{ hotel.id }}">Details</button>
|
||||
<hr />
|
||||
</div>
|
||||
} @empty {
|
||||
<h1>no matching results for {{ search }}</h1>
|
||||
}
|
||||
`,
|
||||
imports: [FormsModule, HotelComponent, AsyncPipe, CurrencyComponent, RouterLink, StarComponent, NgIf],
|
||||
imports: [
|
||||
FormsModule,
|
||||
HotelComponent,
|
||||
AsyncPipe,
|
||||
CurrencyComponent,
|
||||
RouterLink,
|
||||
StarComponent,
|
||||
NgIf,
|
||||
],
|
||||
providers: [HotelService],
|
||||
selector: 'app-hotels',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class HotelsComponent {
|
||||
|
||||
public currency: Lang = {name: 'de', code: 'de-DE', currency: 'EUR'};
|
||||
public currency: Lang = { name: 'de', code: 'de-DE', currency: 'EUR' };
|
||||
|
||||
public search: string = '';
|
||||
|
||||
private hotelService: HotelService= inject(HotelService);
|
||||
private hotelService: HotelService = inject(HotelService);
|
||||
|
||||
public matchingHotels: Observable<Hotel[]> = this.hotelService.getHotels();
|
||||
|
||||
public searchEvent(input: string) {
|
||||
this.search = input.toLowerCase();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-star',
|
||||
@ -6,10 +6,32 @@ import {Component, Input} from '@angular/core';
|
||||
imports: [],
|
||||
template: `
|
||||
@for (_ of getList(); track null) {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" color="yellow"><path fill="currentColor" d="m5.825 21l1.625-7.025L2 9.25l7.2-.625L12 2l2.8 6.625l7.2.625l-5.45 4.725L18.175 21L12 17.275z"/></svg>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
color="yellow"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="m5.825 21l1.625-7.025L2 9.25l7.2-.625L12 2l2.8 6.625l7.2.625l-5.45 4.725L18.175 21L12 17.275z"
|
||||
/>
|
||||
</svg>
|
||||
}
|
||||
@if (rating % 1 >= 0.5) {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" color="yellow"><path fill="currentColor" d="M12 2L9.19 8.62L2 9.24l5.45 4.73L5.82 21L12 17.27z"/></svg>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
color="yellow"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2L9.19 8.62L2 9.24l5.45 4.73L5.82 21L12 17.27z"
|
||||
/>
|
||||
</svg>
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
@ -2,8 +2,8 @@ export interface Hotel {
|
||||
id: number;
|
||||
hotelName: string;
|
||||
description: string;
|
||||
email: string|null,
|
||||
phoneNumber: string|null,
|
||||
email: string | null;
|
||||
phoneNumber: string | null;
|
||||
price: number;
|
||||
imageUrl: string;
|
||||
rating: number;
|
||||
|
@ -1,57 +1,55 @@
|
||||
import {InMemoryDbService} from "angular-in-memory-web-api";
|
||||
import {Hotel} from "../model/hotel";
|
||||
import { InMemoryDbService } from 'angular-in-memory-web-api';
|
||||
import { Hotel } from '../model/hotel';
|
||||
|
||||
|
||||
export class HotelDataService implements InMemoryDbService{
|
||||
export class HotelDataService implements InMemoryDbService {
|
||||
createDb(): Record<string, Hotel[]> {
|
||||
const hotels: Hotel[] = [
|
||||
{
|
||||
"id": 1,
|
||||
"hotelName": "Buea süßes Leben",
|
||||
"description": "Schöne Aussicht am Meer",
|
||||
"price": 230.5,
|
||||
"imageUrl": "assets/img/heisenberg.jpg",
|
||||
"rating": 3.5,
|
||||
"tags": ["Meer", "Berge"],
|
||||
"email": "buea@mail.com",
|
||||
"phoneNumber": "1234567890"
|
||||
id: 1,
|
||||
hotelName: 'Buea süßes Leben',
|
||||
description: 'Schöne Aussicht am Meer',
|
||||
price: 230.5,
|
||||
imageUrl: 'assets/img/heisenberg.jpg',
|
||||
rating: 3.5,
|
||||
tags: ['Meer', 'Berge'],
|
||||
email: 'buea@mail.com',
|
||||
phoneNumber: '1234567890',
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"hotelName": "Marrakesch",
|
||||
"description": "Genießen Sie den Blick auf die Berge",
|
||||
"price": 145.5,
|
||||
"imageUrl": "assets/img/kjan.png",
|
||||
"rating": 5,
|
||||
"tags": ["Meer", "Berge"],
|
||||
"email": "marrakesch@mail.com",
|
||||
"phoneNumber": "1234567890"
|
||||
id: 2,
|
||||
hotelName: 'Marrakesch',
|
||||
description: 'Genießen Sie den Blick auf die Berge',
|
||||
price: 145.5,
|
||||
imageUrl: 'assets/img/kjan.png',
|
||||
rating: 5,
|
||||
tags: ['Meer', 'Berge'],
|
||||
email: 'marrakesch@mail.com',
|
||||
phoneNumber: '1234567890',
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"hotelName": "Abuja neuer Palast",
|
||||
"description": "Kompletter Aufenthalt mit Autoservice",
|
||||
"price": 120.12,
|
||||
"imageUrl": "assets/img/huy.png",
|
||||
"rating": 4,
|
||||
"tags": ["Meer", "Berge"],
|
||||
"email": "abuja@mail.com",
|
||||
"phoneNumber": "1234567890"
|
||||
id: 3,
|
||||
hotelName: 'Abuja neuer Palast',
|
||||
description: 'Kompletter Aufenthalt mit Autoservice',
|
||||
price: 120.12,
|
||||
imageUrl: 'assets/img/huy.png',
|
||||
rating: 4,
|
||||
tags: ['Meer', 'Berge'],
|
||||
email: 'abuja@mail.com',
|
||||
phoneNumber: '1234567890',
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"hotelName": "OUR Hotel",
|
||||
"description": "Wunderschönes Ambiente für Ihren Aufenthalt",
|
||||
"price": 135.12,
|
||||
"imageUrl": "assets/img/rat.png",
|
||||
"rating": 2.5,
|
||||
"tags": ["Meer", "Berge"],
|
||||
"email": "our@mail.com",
|
||||
"phoneNumber": "1234567890"
|
||||
}
|
||||
id: 4,
|
||||
hotelName: 'OUR Hotel',
|
||||
description: 'Wunderschönes Ambiente für Ihren Aufenthalt',
|
||||
price: 135.12,
|
||||
imageUrl: 'assets/img/rat.png',
|
||||
rating: 2.5,
|
||||
tags: ['Meer', 'Berge'],
|
||||
email: 'our@mail.com',
|
||||
phoneNumber: '1234567890',
|
||||
},
|
||||
];
|
||||
|
||||
return { hotels };
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {inject, Injectable} from "@angular/core";
|
||||
import {Observable, shareReplay} from "rxjs";
|
||||
import {Hotel} from "../model/hotel";
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Observable, shareReplay } from 'rxjs';
|
||||
import { Hotel } from '../model/hotel';
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class HotelService {
|
||||
private httpClient: HttpClient = inject(HttpClient);
|
||||
@ -18,11 +18,11 @@ export class HotelService {
|
||||
}
|
||||
|
||||
public updateHotelById(hotel: Hotel): Observable<Object> {
|
||||
return this.httpClient.put<Hotel>(`/api/hotels/${hotel.id}`, hotel)
|
||||
return this.httpClient.put<Hotel>(`/api/hotels/${hotel.id}`, 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> {
|
||||
|
@ -1,15 +1,26 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>HotelManager</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js" integrity="sha512-ykZ1QQr0Jy/4ZkvKuqWn4iF3lqPZyij9iRv6sGqLRdTPkY69YX6+7wvVGmsdBbiIfN/8OdsI7HABjvEok6ZopQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-grid.min.css" integrity="sha512-i1b/nzkVo97VN5WbEtaPebBG8REvjWeqNclJ6AItj7msdVcaveKrlIIByDpvjk5nwHjXkIqGZscVxOrTb9tsMA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js"
|
||||
integrity="sha512-ykZ1QQr0Jy/4ZkvKuqWn4iF3lqPZyij9iRv6sGqLRdTPkY69YX6+7wvVGmsdBbiIfN/8OdsI7HABjvEok6ZopQ=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-grid.min.css"
|
||||
integrity="sha512-i1b/nzkVo97VN5WbEtaPebBG8REvjWeqNclJ6AItj7msdVcaveKrlIIByDpvjk5nwHjXkIqGZscVxOrTb9tsMA=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,5 +2,6 @@ import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig)
|
||||
.catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user