diff --git a/angular/RestClient/src/app/app.component.spec.ts b/angular/RestClient/src/app/app.component.spec.ts index ab77de0d1b761c50efffa4c4fcbc31e301eb01a0..360bd69b802b5865ce5bb94b3a5ed758dbc09b26 100644 --- a/angular/RestClient/src/app/app.component.spec.ts +++ b/angular/RestClient/src/app/app.component.spec.ts @@ -1,10 +1,11 @@ import { TestBed } from '@angular/core/testing'; import { AppComponent } from './app.component'; +import { ReactiveFormsModule } from '@angular/forms'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [AppComponent], + imports: [AppComponent, ReactiveFormsModule], }).compileComponents(); }); diff --git a/angular/RestClient/src/app/app.config.ts b/angular/RestClient/src/app/app.config.ts index 4f22ef91221d03c2345431c665993b2683b2c7e5..74b690e0f85b3d2c692cb8d1d0e9b067c6b6ad95 100644 --- a/angular/RestClient/src/app/app.config.ts +++ b/angular/RestClient/src/app/app.config.ts @@ -1,16 +1,19 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; - import { routes } from './app.routes'; import { provideClientHydration } from '@angular/platform-browser'; import { provideHttpClient, withFetch } from '@angular/common/http'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import { importProvidersFrom } from '@angular/core'; +import { ReactiveFormsModule } from '@angular/forms'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideClientHydration(), - provideHttpClient(withFetch()), provideAnimationsAsync(), + provideHttpClient(withFetch()), + provideAnimationsAsync(), + ReactiveFormsModule // Asegúrate de incluir ReactiveFormsModule ], }; diff --git a/angular/RestClient/src/app/app.routes.ts b/angular/RestClient/src/app/app.routes.ts index 1a20159cf83a05e3b4a62a42943c37b05bc09297..1787d715684c20bc00d416731fa0ecf6d59b4ab3 100644 --- a/angular/RestClient/src/app/app.routes.ts +++ b/angular/RestClient/src/app/app.routes.ts @@ -1,5 +1,6 @@ import { Routes } from '@angular/router'; import { HotelListComponent } from './hotel-list/hotel-list.component'; +import { BookingComponent } from './booking/booking.component'; // Asegúrate de ajustar la ruta export const routes: Routes = [ { @@ -7,7 +8,11 @@ export const routes: Routes = [ component: HotelListComponent, }, { - path: '**', + path: 'booking', // Añade la ruta para el componente de reservas + component: BookingComponent, + }, + { + path: '**', // Mantiene la redirección para cualquier otra ruta no definida redirectTo: 'hotels', pathMatch: 'full', }, diff --git a/angular/RestClient/src/app/booking.service.spec.ts b/angular/RestClient/src/app/booking.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3992ef555abf9021f683a3b7fd42344842c4d6ed --- /dev/null +++ b/angular/RestClient/src/app/booking.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { BookingService } from './booking.service'; + +describe('BookingService', () => { + let service: BookingService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BookingService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/angular/RestClient/src/app/booking.service.ts b/angular/RestClient/src/app/booking.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..454cc15666e3703595b17b4df677b97282cfe0fb --- /dev/null +++ b/angular/RestClient/src/app/booking.service.ts @@ -0,0 +1,47 @@ +// booking.service.ts +import { Injectable } from '@angular/core'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Observable } from 'rxjs'; +interface BookingRequest { + userId: number; // ID del usuario que realiza la reserva + hotelId: number; // ID del hotel en el que se realiza la reserva + roomType: string; // Tipo de habitación (single, double, suite) + startDate: string; // Fecha de inicio de la reserva + endDate: string; // Fecha de fin de la reserva +} +import { Booking } from '../types/Booking'; // Ajusta la ruta a tu modelo Booking + +@Injectable({ + providedIn: 'root' // Esto hace que el servicio esté disponible en toda la aplicación +}) +export class BookingService { + private apiUrl = 'http://localhost:8080/api/bookings'; // Cambia esta URL a la de tu API + + constructor(private http: HttpClient) {} + + // Método para crear una nueva reserva + createBooking(bookingRequest: BookingRequest): Observable<Booking> { + return this.http.post<Booking>(this.apiUrl, bookingRequest, { + headers: new HttpHeaders({ + 'Content-Type': 'application/json' + }) + }); + } + + // Método para obtener todas las reservas + getAllBookings(): Observable<Booking[]> { + return this.http.get<Booking[]>(this.apiUrl); + } + + // Método para obtener una reserva por ID + getBookingById(id: number): Observable<Booking> { + return this.http.get<Booking>(`${this.apiUrl}/${id}`); + } + + // Método para eliminar una reserva + deleteBooking(id: number): Observable<void> { + return this.http.delete<void>(`${this.apiUrl}/${id}`); + } + + // Agrega más métodos según sea necesario +} diff --git a/angular/RestClient/src/app/booking/booking.component.css b/angular/RestClient/src/app/booking/booking.component.css new file mode 100644 index 0000000000000000000000000000000000000000..34f19bda870b7fe9ab1df89627e400529a8b543f --- /dev/null +++ b/angular/RestClient/src/app/booking/booking.component.css @@ -0,0 +1,26 @@ +.container { + max-width: 600px; + margin: auto; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f9f9f9; + } + + h2 { + text-align: center; + margin-bottom: 20px; + } + + .form-group { + margin-bottom: 15px; + } + + label { + font-weight: bold; + } + + .btn { + width: 100%; + } + \ No newline at end of file diff --git a/angular/RestClient/src/app/booking/booking.component.html b/angular/RestClient/src/app/booking/booking.component.html new file mode 100644 index 0000000000000000000000000000000000000000..9519beb52a3a7473223fe13ffc3c51abbf9c5032 --- /dev/null +++ b/angular/RestClient/src/app/booking/booking.component.html @@ -0,0 +1,37 @@ +<div class="container"> + <h2>Crear Reserva</h2> + <form [formGroup]="bookingForm" (ngSubmit)="submitBooking()"> + <div class="form-group"> + <label for="userId">ID del Usuario:</label> + <input type="number" id="userId" formControlName="userId" class="form-control" /> + </div> + + <div class="form-group"> + <label for="hotelId">ID del Hotel:</label> + <input type="number" id="hotelId" formControlName="hotelId" class="form-control" /> + </div> + + <div class="form-group"> + <label for="roomType">Tipo de Habitación:</label> + <select id="roomType" formControlName="roomType" class="form-control"> + <option value="">Seleccione</option> + <option value="single">Individual</option> + <option value="double">Doble</option> + <option value="suite">Suite</option> + </select> + </div> + + <div class="form-group"> + <label for="startDate">Fecha de Inicio:</label> + <input type="date" id="startDate" formControlName="startDate" class="form-control" /> + </div> + + <div class="form-group"> + <label for="endDate">Fecha de Fin:</label> + <input type="date" id="endDate" formControlName="endDate" class="form-control" /> + </div> + + <button type="submit" class="btn btn-primary">Reservar</button> + </form> + </div> + \ No newline at end of file diff --git a/angular/RestClient/src/app/booking/booking.component.spec.ts b/angular/RestClient/src/app/booking/booking.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0a8d9ea7b6fb3a520a401263b587ba7361b34989 --- /dev/null +++ b/angular/RestClient/src/app/booking/booking.component.spec.ts @@ -0,0 +1,56 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { BookingComponent } from './booking.component'; +import { BookingService } from '../booking.service'; +import { of } from 'rxjs'; + +class MockBookingService { + createBooking() { + return of({}); // Simula una respuesta exitosa + } +} + +describe('BookingComponent', () => { + let component: BookingComponent; + let fixture: ComponentFixture<BookingComponent>; + let bookingService: BookingService; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BookingComponent], + imports: [ReactiveFormsModule], + providers: [{ provide: BookingService, useClass: MockBookingService }] + }).compileComponents(); + + fixture = TestBed.createComponent(BookingComponent); + component = fixture.componentInstance; + bookingService = TestBed.inject(BookingService); + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should have a valid form when all fields are filled', () => { + component.bookingForm.controls['userId'].setValue(1); + component.bookingForm.controls['hotelId'].setValue(1); + component.bookingForm.controls['roomType'].setValue('single'); + component.bookingForm.controls['startDate'].setValue('2024-10-01'); + component.bookingForm.controls['endDate'].setValue('2024-10-05'); + + expect(component.bookingForm.valid).toBeTrue(); + }); + + it('should submit booking when form is valid', () => { + spyOn(bookingService, 'createBooking').and.callThrough(); + component.bookingForm.controls['userId'].setValue(1); + component.bookingForm.controls['hotelId'].setValue(1); + component.bookingForm.controls['roomType'].setValue('single'); + component.bookingForm.controls['startDate'].setValue('2024-10-01'); + component.bookingForm.controls['endDate'].setValue('2024-10-05'); + + component.submitBooking(); + expect(bookingService.createBooking).toHaveBeenCalled(); + }); +}); diff --git a/angular/RestClient/src/app/booking/booking.component.ts b/angular/RestClient/src/app/booking/booking.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..79bd281d858872344fe2cf0456c7ee2ab5aea57e --- /dev/null +++ b/angular/RestClient/src/app/booking/booking.component.ts @@ -0,0 +1,54 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +interface BookingRequest { + userId: number; // ID del usuario que realiza la reserva + hotelId: number; // ID del hotel en el que se realiza la reserva + roomType: string; // Tipo de habitación (single, double, suite) + startDate: string; // Fecha de inicio de la reserva + endDate: string; // Fecha de fin de la reserva// Asegúrate de ajustar la ruta +} +import { BookingService } from '../booking.service'; // Asegúrate de que el servicio exista + +@Component({ + selector: 'app-booking', + templateUrl: './booking.component.html', + styleUrls: ['./booking.component.css'] +}) +export class BookingComponent implements OnInit { + bookingForm: FormGroup; + + constructor(private fb: FormBuilder, private bookingService: BookingService) { + // Inicialización del formulario con validaciones + this.bookingForm = this.fb.group({ + userId: ['', Validators.required], + hotelId: ['', Validators.required], + roomType: ['', Validators.required], + startDate: ['', Validators.required], + endDate: ['', Validators.required] + }); + } + + ngOnInit(): void {} + + submitBooking() { + if (this.bookingForm.valid) { + const bookingRequest: BookingRequest = this.bookingForm.value; + + // Llama al servicio para crear una nueva reserva + this.bookingService.createBooking(bookingRequest).subscribe( + response => { + console.log('Reserva creada con éxito', response); + // Aquí puedes redirigir al usuario o mostrar un mensaje de éxito + this.bookingForm.reset(); // Opcional: resetea el formulario después de una reserva exitosa + }, + error => { + console.error('Error al crear la reserva', error); + // Manejo de errores + } + ); + } else { + console.warn('El formulario no es válido'); + // Puedes mostrar un mensaje al usuario sobre la validez del formulario + } + } +} diff --git a/angular/RestClient/src/app/shared/cliente-api-rest.service.ts b/angular/RestClient/src/app/shared/cliente-api-rest.service.ts index 1def3e16d28352b9458248b2045a68229d052f57..7cc9d40607f696d2c133f87aa027d5e872dc4ca8 100644 --- a/angular/RestClient/src/app/shared/cliente-api-rest.service.ts +++ b/angular/RestClient/src/app/shared/cliente-api-rest.service.ts @@ -1,8 +1,9 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; import hotels from '../../mocks/hotels.json'; -import { Hotel } from '../../types'; +import { Hotel, Booking } from '../../types'; @Injectable({ providedIn: 'root', @@ -45,4 +46,9 @@ export class ClienteApiRestService { } ); } + + createBooking(bookingRequest: Booking): Observable<any> { + return this.http.post('http://localhost:8080/bookings', bookingRequest); + } + } diff --git a/angular/RestClient/src/types/index.ts b/angular/RestClient/src/types/index.ts index 8ec625599a2be411714cc097745fc0357cd5b229..958d57e8a39f47ec45f9a33857cf52f3aacfde34 100644 --- a/angular/RestClient/src/types/index.ts +++ b/angular/RestClient/src/types/index.ts @@ -2,4 +2,5 @@ export type * from './User'; export type * from './Address'; export type * from './Hotel'; export type * from './Room'; +export type * from './Booking'; export type * from './User';