From 0ba462f7858e15974f8079084e418b77c675e8c7 Mon Sep 17 00:00:00 2001
From: migudel <miguel.moras@estudiantes.uva.es>
Date: Sun, 3 Nov 2024 12:45:44 +0100
Subject: [PATCH] Agregado vista de reservas de usuario

---
 .../bookings/booking/booking.component.ts     | 18 +++++--
 .../user/main-page/main-page.component.html   | 14 ++++--
 .../user/main-page/main-page.component.ts     |  3 +-
 .../user-booking-list.component.html          | 25 +++++++++-
 .../user-booking-list.component.ts            | 48 ++++++++++++++++++-
 .../app/shared/cliente-api-rest.service.ts    | 22 ++++++++-
 angular/RestClient/src/types/Booking.d.ts     |  4 +-
 angular/RestClient/src/types/User.d.ts        |  7 ++-
 angular/package-lock.json                     |  6 ---
 .../Controllers/UserController.java           | 29 +++++++----
 .../Repositories/BookingRepository.java       |  3 --
 11 files changed, 144 insertions(+), 35 deletions(-)
 delete mode 100644 angular/package-lock.json

diff --git a/angular/RestClient/src/app/core/features/bookings/booking/booking.component.ts b/angular/RestClient/src/app/core/features/bookings/booking/booking.component.ts
index 803417a..caa8887 100644
--- a/angular/RestClient/src/app/core/features/bookings/booking/booking.component.ts
+++ b/angular/RestClient/src/app/core/features/bookings/booking/booking.component.ts
@@ -7,7 +7,7 @@ import {
 } from '@angular/forms';
 
 import { BookingService } from '../../../../shared/booking.service'; // Asegúrate de que el servicio exista
-import { ActivatedRoute } from '@angular/router';
+import { ActivatedRoute, Router } from '@angular/router';
 import { Booking } from '../../../../../types';
 
 @Component({
@@ -22,6 +22,7 @@ export class BookingComponent implements OnInit {
   roomId: number = 0;
 
   constructor(
+    private router: Router,
     private route: ActivatedRoute,
     private fb: FormBuilder,
     private bookingService: BookingService
@@ -45,9 +46,10 @@ export class BookingComponent implements OnInit {
   submitBooking() {
     if (this.bookingForm.valid) {
       const formValue = this.bookingForm.value;
+      const { userId } = formValue;
       const bookingRequest: Booking = {
         ...formValue,
-        userId: { id: formValue.userId },
+        userId: { id: userId },
         roomId: { id: formValue.roomId },
       };
       console.warn(bookingRequest);
@@ -56,8 +58,16 @@ export class BookingComponent implements OnInit {
       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
+          // Llama al servicio para actualizar el estado del usuario
+          this.bookingService.createBooking(bookingRequest).subscribe({
+            next: (response) => {
+              console.log('Reserva creada con éxito', response);
+            },
+            error: (error) => {
+              console.error('Error al crear la reserva', error);
+            },
+          });
+          this.router.navigate(['/user', userId, 'bookings']);
         },
         (error) => {
           console.error('Error al crear la reserva', error);
diff --git a/angular/RestClient/src/app/core/features/user/main-page/main-page.component.html b/angular/RestClient/src/app/core/features/user/main-page/main-page.component.html
index 35ecb31..0685752 100644
--- a/angular/RestClient/src/app/core/features/user/main-page/main-page.component.html
+++ b/angular/RestClient/src/app/core/features/user/main-page/main-page.component.html
@@ -12,10 +12,14 @@
   </div>
 
   <ul class="user-list">
-    <li *ngFor="let user of filteredUsers" class="user-item">
-      <span class="user-name">{{ user.name }}</span>
-      <span class="user-email">{{ user.email }}</span>
-      <span class="user-status">{{ user.status }}</span>
-    </li>
+    @for (user of filteredUsers; track user.id) {
+    <a [routerLink]="['/users', user.id, 'bookings']">
+      <li class="user-item">
+        <span class="user-name">{{ user.name }}</span>
+        <span class="user-email">{{ user.email }}</span>
+        <span class="user-status">{{ user.status }}</span>
+      </li>
+    </a>
+    }
   </ul>
 </div>
diff --git a/angular/RestClient/src/app/core/features/user/main-page/main-page.component.ts b/angular/RestClient/src/app/core/features/user/main-page/main-page.component.ts
index 4d31d5f..e1f7201 100644
--- a/angular/RestClient/src/app/core/features/user/main-page/main-page.component.ts
+++ b/angular/RestClient/src/app/core/features/user/main-page/main-page.component.ts
@@ -5,9 +5,10 @@ import { User } from '../../../../../types';
 import { FormsModule } from '@angular/forms';
 import { CommonModule } from '@angular/common';
 import users from '../../../../../mocks/users.json';
+import { RouterModule } from '@angular/router';
 @Component({
   standalone: true,
-  imports: [FormsModule, CommonModule],
+  imports: [FormsModule, CommonModule, RouterModule],
   selector: 'app-main-page',
   templateUrl: './main-page.component.html',
   styleUrls: ['./main-page.component.css'],
diff --git a/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.html b/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.html
index 75ada56..2df122e 100644
--- a/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.html
+++ b/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.html
@@ -1 +1,24 @@
-<p>user-booking-list works!</p>
+<div class="booking-container">
+  <h1>Listado de Reservas</h1>
+
+  <div class="filter-container">
+    <label for="filter">Filtrar por estado:</label>
+    <select id="filter" [(ngModel)]="selectedState" (change)="updateBookings()">
+      <option value="all">Todas</option>
+      <option value="active">Reservas activas</option>
+      <option value="inactive">Reservas inactivas</option>
+    </select>
+  </div>
+
+  <ul class="booking-list">
+    @for( booking of bookings; track booking.id) {
+    <li class="booking-item">
+      <span class="booking-id">Reserva #{{ booking.id }}</span>
+      <span class="booking-dates"
+        >{{ booking.startDate }} - {{ booking.endDate }}</span
+      >
+      <span class="booking-status">{{ genBookingState(booking) }}</span>
+    </li>
+    }
+  </ul>
+</div>
diff --git a/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.ts b/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.ts
index 568e58c..76220e6 100644
--- a/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.ts
+++ b/angular/RestClient/src/app/core/features/user/user-booking-list/user-booking-list.component.ts
@@ -1,12 +1,56 @@
 import { Component } from '@angular/core';
+import { ClienteApiRestService } from '../../../../shared/cliente-api-rest.service';
+import { Booking } from '../../../../../types';
+import { ActivatedRoute, RouterModule } from '@angular/router';
+import { MatSelectModule } from '@angular/material/select';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+type state = 'all' | 'active' | 'inactive';
 
 @Component({
   selector: 'app-user-booking-list',
   standalone: true,
-  imports: [],
+  imports: [FormsModule, CommonModule, RouterModule],
   templateUrl: './user-booking-list.component.html',
-  styleUrl: './user-booking-list.component.css'
+  styleUrl: './user-booking-list.component.css',
 })
 export class UserBookingListComponent {
+  selectedState: state = 'all';
+  bookings: Booking[] = [];
+  userId: number = 0;
+
+  constructor(
+    private client: ClienteApiRestService,
+    private route: ActivatedRoute
+  ) {
+    this.route.paramMap.subscribe({
+      next: (params) => {
+        this.userId = Number(params.get('id'));
+        this.updateBookings();
+      },
+    });
+  }
+
+  ngOnInit() {
+    this.updateBookings();
+  }
+
+  updateBookings() {
+    this.client.getUserBookings(this.userId).subscribe({
+      next: (bookings) => {
+        this.bookings = bookings;
+        console.log({ bookings });
+      },
+      error: (error) => {
+        console.error(error);
+      },
+    });
+  }
 
+  genBookingState(booking: Booking) {
+    return new Date(booking.endDate).getTime() < Date.now()
+      ? 'Reserva inactiva'
+      : 'Reserva activa';
+  }
 }
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 6cfa26d..31c4590 100644
--- a/angular/RestClient/src/app/shared/cliente-api-rest.service.ts
+++ b/angular/RestClient/src/app/shared/cliente-api-rest.service.ts
@@ -1,7 +1,6 @@
 import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
-import { Hotel, Booking, Room } from '../../types';
-import { Observable } from 'rxjs';
+import { Hotel, Booking, Room, UserState } from '../../types';
 import { User } from '../../types';
 
 @Injectable({
@@ -69,4 +68,23 @@ export class ClienteApiRestService {
       observe: 'body',
     });
   }
+
+  getUserBookings(userId: number) {
+    return this.http.get<Booking[]>(
+      `${ClienteApiRestService.BASE_URI}/users/${userId}/bookings`
+    );
+  }
+
+  alterUserStatus(status: UserState) {
+    return this.http.patch(
+      `${ClienteApiRestService.BASE_URI}/users`,
+      {
+        status,
+      },
+      {
+        observe: 'response',
+        responseType: 'text',
+      }
+    );
+  }
 }
diff --git a/angular/RestClient/src/types/Booking.d.ts b/angular/RestClient/src/types/Booking.d.ts
index aac08c6..797c8aa 100644
--- a/angular/RestClient/src/types/Booking.d.ts
+++ b/angular/RestClient/src/types/Booking.d.ts
@@ -5,6 +5,6 @@ export interface Booking {
   id: number;
   startDate: Date;
   endDate: Date;
-  user: User;
-  room: Room;
+  userId: User;
+  roomId: Room;
 }
diff --git a/angular/RestClient/src/types/User.d.ts b/angular/RestClient/src/types/User.d.ts
index ac99f9d..09a0ec8 100644
--- a/angular/RestClient/src/types/User.d.ts
+++ b/angular/RestClient/src/types/User.d.ts
@@ -3,5 +3,10 @@ export interface User {
   name: string;
   email: String;
   // status: "noBookings" | "withActiveBookings" | "withInactiveBookings";
-  status: 'NO_BOOKINGS' | 'WITH_ACTIVE_BOOKINGS' | 'WITH_INACTIVE_BOOKINGS';
+  status: UserState;
 }
+
+export type UserState =
+  | 'NO_BOOKINGS'
+  | 'WITH_ACTIVE_BOOKINGS'
+  | 'WITH_INACTIVE_BOOKINGS';
diff --git a/angular/package-lock.json b/angular/package-lock.json
deleted file mode 100644
index 2e8ea37..0000000
--- a/angular/package-lock.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "name": "angular",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {}
-}
diff --git a/java/roomBooking/src/main/java/com/uva/roomBooking/Controllers/UserController.java b/java/roomBooking/src/main/java/com/uva/roomBooking/Controllers/UserController.java
index a2e8961..a336822 100644
--- a/java/roomBooking/src/main/java/com/uva/roomBooking/Controllers/UserController.java
+++ b/java/roomBooking/src/main/java/com/uva/roomBooking/Controllers/UserController.java
@@ -1,5 +1,6 @@
 package com.uva.roomBooking.Controllers;
 
+import java.time.LocalDate;
 import java.util.List;
 import java.util.Map;
 
@@ -17,7 +18,6 @@ import org.springframework.web.bind.annotation.RestController;
 import com.uva.roomBooking.Models.UserStatus;
 import com.uva.roomBooking.Models.Booking;
 import com.uva.roomBooking.Models.User;
-import com.uva.roomBooking.Repositories.BookingRepository;
 import com.uva.roomBooking.Repositories.UserRepository;
 
 @RestController
@@ -25,11 +25,9 @@ import com.uva.roomBooking.Repositories.UserRepository;
 @CrossOrigin(origins = "*")
 public class UserController {
   private final UserRepository userRepository;
-  private final BookingRepository bookingRepository;
 
-  public UserController(UserRepository userRepository, BookingRepository bookingRepository) {
+  public UserController(UserRepository userRepository) {
     this.userRepository = userRepository;
-    this.bookingRepository = bookingRepository;
   }
 
   @GetMapping
@@ -71,17 +69,32 @@ public class UserController {
       throw new RuntimeException("Missing required fields");
     }
     UserStatus userStatus = UserStatus.valueOf(strStatus);
+
+    // TODO decicir cual va a ser nuestra politica
+    boolean activeBookings = target.getBookings().stream()
+        .anyMatch(booking -> booking.getEndDate().isAfter(LocalDate.now())); // reserva > ahora
+    // boolean activeBookings = target.getBookings().stream().anyMatch(booking ->
+    // !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora
+    boolean inactiveBookings = target.getBookings().stream()
+        .anyMatch(booking -> booking.getStartDate().isBefore(LocalDate.now())); // reserva < ahora
+    // boolean inactiveBookings = target.getBookings().stream().anyMatch(booking ->
+    // !booking.getStartDate().isAfter(LocalDate.now())); // reserva <= ahora
+
     switch (userStatus) {
       // TODO Buscar como validar las (in)active bookings
       case NO_BOOKINGS:
         if (!target.getBookings().isEmpty())
-          throw new IllegalArgumentException("Invalid State: The user have at least one booking");
+          throw new IllegalArgumentException("Invalid State: The user has at least one booking");
       case WITH_ACTIVE_BOOKINGS:
         if (target.getBookings().isEmpty())
-          throw new IllegalArgumentException("Invalid State: The user don't have bookings");
+          throw new IllegalArgumentException("Invalid State: The user don't has bookings");
+        if (!activeBookings)
+          throw new IllegalArgumentException("Invalid State: The user don't has active bookings");
       case WITH_INACTIVE_BOOKINGS:
         if (target.getBookings().isEmpty())
-          throw new IllegalArgumentException("Invalid State: The user don't have bookings");
+          throw new IllegalArgumentException("Invalid State: The user don't has bookings");
+        if (!inactiveBookings)
+          throw new IllegalArgumentException("Invalid State: The user don't has inactive bookings");
       default:
         break;
     }
@@ -101,6 +114,6 @@ public class UserController {
   @GetMapping("/{id}/bookings")
   public List<Booking> getUserBookingsById(@PathVariable int id) {
     User user = userRepository.findById(id).orElseThrow();
-    return bookingRepository.findByUserId(user);
+    return user.getBookings();
   }
 }
diff --git a/java/roomBooking/src/main/java/com/uva/roomBooking/Repositories/BookingRepository.java b/java/roomBooking/src/main/java/com/uva/roomBooking/Repositories/BookingRepository.java
index d988f40..a010a3a 100644
--- a/java/roomBooking/src/main/java/com/uva/roomBooking/Repositories/BookingRepository.java
+++ b/java/roomBooking/src/main/java/com/uva/roomBooking/Repositories/BookingRepository.java
@@ -2,7 +2,6 @@
 package com.uva.roomBooking.Repositories;
 
 import com.uva.roomBooking.Models.Booking;
-import com.uva.roomBooking.Models.User;
 
 import java.time.LocalDate;
 import java.util.List;
@@ -13,8 +12,6 @@ import org.springframework.data.repository.query.Param;
 
 public interface BookingRepository extends JpaRepository<Booking, Integer> {
 
-    List<Booking> findByUserId(User userId);
-
     @Query("SELECT b FROM Booking b WHERE b.roomId.id = ?1 AND b.startDate < ?2 AND b.endDate > ?3")
     List<Booking> findByRoomIdAndDateRange(@Param("roomId") int roomId, @Param("startDate") LocalDate startDate,
             @Param("endDate") LocalDate endDate);
-- 
GitLab