Skip to main content

Overview

Making a reservation on Trippins is a straightforward process that allows registered users to book accommodations for specific dates. This guide covers the complete reservation workflow, from browsing properties to confirming your booking.
You must be logged in to make reservations. Anonymous users need to register or log in first.

Prerequisites

Before making a reservation, ensure you have:

User Account

Register and log in to the platform

JWT Token

Valid authentication token stored

Property Selected

Navigate to a specific property detail page

Available Dates

Know your check-in and check-out dates

Reservation Data Structure

Each reservation contains the following information:
interface ReservationDTO {
  id?: number;           // Auto-generated
  checkIn: Date;         // Check-in date
  checkOut: Date;        // Check-out date
  valorated: boolean;    // Has user reviewed?
  clientDni: string;     // User's DNI
  housingCode: number;   // Property code
  housingName: string;   // Property name
}

Making a Reservation

Step-by-Step Process

1

Navigate to property details

Go to /room/{code} to view a specific property
2

Fill reservation form

Enter check-in and check-out dates in the booking form
3

Submit reservation

Click the booking button to create your reservation
4

Confirmation

Receive success notification with booking details

Reservation Form Component

@Component({
  selector: 'app-room-details',
  templateUrl: './room-details.component.html'
})
export class RoomDetailsComponent {
  reservationForm: FormGroup;
  clientDni: string | null = null;

  constructor(
    private fb: FormBuilder,
    public authService: AuthService,
    private reservationService: ReservationServiceService
  ) {
    this.reservationForm = this.fb.group({
      checkIn: ['', Validators.required],
      checkOut: ['', Validators.required]
    });
  }

  ngOnInit(): void {
    // Get current user's DNI
    this.authService.getUserDni().subscribe(dni => {
      this.clientDni = dni;
    });
  }
}

Form Validation

The reservation form validates:
Both check-in and check-out dates are mandatory fields
Check-out date should be after check-in date (implement custom validator)
User must be logged in (authService.isLoggedIn())
A valid housing property must be selected

Submitting the Reservation

onSubmitReservation(): void {
  // Validate form and authentication
  if (this.reservationForm.invalid || !this.house || !this.authService.isLoggedIn()) {
    return;
  }

  // Prepare reservation data
  const reservationData = {
    ...this.reservationForm.value,
    housingCode: this.house.code,
    housingName: this.house.name,
    clientDni: this.clientDni,
    valorated: false  // Initially not reviewed
  };

  // Submit to API
  this.reservationService.createReservation(reservationData).subscribe({
    next: () => {
      Swal.fire({
        title: '¡Reserva exitosa! 🎉',
        text: 'Tu reserva fue creada correctamente.',
        icon: 'success',
        confirmButtonText: '¡Genial!'
      });
      this.reservationForm.reset();
    },
    error: (err: any) => {
      console.error('Error creating reservation:', err);
      Swal.fire({
        title: 'Oops 😬',
        text: 'Hubo un error al crear la reserva.',
        icon: 'error',
        confirmButtonText: 'Intentar de nuevo'
      });
    }
  });
}
The valorated field tracks whether the user has written a review for this reservation. It’s initially set to false and updated to true after submitting a review.

API Endpoints

Create Reservation

POST /v1/api/reservations

Create a new reservation (requires authentication)
checkIn
Date
required
Check-in date in SQL date format (YYYY-MM-DD)
checkOut
Date
required
Check-out date in SQL date format (YYYY-MM-DD)
clientDni
string
required
User’s DNI from authenticated session
housingCode
number
required
Property code to reserve
housingName
string
required
Property name for reference
valorated
boolean
default:"false"
Review status (always false on creation)
curl -X POST http://localhost:8080/v1/api/reservations \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "checkIn": "2026-06-01",
    "checkOut": "2026-06-05",
    "clientDni": "12345678A",
    "housingCode": 5,
    "housingName": "Ocean View Resort",
    "valorated": false
  }'

Backend Controller

@RestController
@RequestMapping("/v1/api/reservations")
@Tag(name = "Reservation Management")
public class ReservationRestController {

    @Autowired
    private ReservationService reservationService;

    @Operation(summary = "Create a new reservation")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "201", description = "Reservation created successfully"),
        @ApiResponse(responseCode = "400", description = "Invalid input"),
        @ApiResponse(responseCode = "403", description = "Forbidden - Access denied")
    })
    @SecurityRequirement(name = "JWT")
    @PostMapping
    public ResponseEntity<ReservationDTO> createReservation(
        @RequestBody ReservationDTO reservation) {
        ReservationDTO createdReservation = reservationService.createReservation(reservation);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdReservation);
    }
}

Managing Reservations

View All Reservations (Admin)

GET /v1/api/reservations

Retrieve all reservations (admin only)
curl http://localhost:8080/v1/api/reservations \
  -H "Authorization: Bearer ADMIN_JWT_TOKEN"

Get Specific Reservation

GET /v1/api/reservations/{id}

Get details of a specific reservation
curl http://localhost:8080/v1/api/reservations/42 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
@GetMapping("/{id}")
@SecurityRequirement(name = "JWT")
public ResponseEntity<ReservationDTO> getReservationById(@PathVariable Integer id) {
    ReservationDTO reservation = reservationService.getReservationById(id);
    return ResponseEntity.ok(reservation);
}

Update Reservation

PUT /v1/api/reservations/{id}

Modify an existing reservation
curl -X PUT http://localhost:8080/v1/api/reservations/42 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "checkIn": "2026-06-02",
    "checkOut": "2026-06-06",
    "clientDni": "12345678A",
    "housingCode": 5,
    "housingName": "Ocean View Resort",
    "valorated": false
  }'
Modifying reservations should be done carefully. Consider implementing business rules such as:
  • Only allow updates before check-in date
  • Send notification emails on changes
  • Log all modifications for audit purposes

Cancel Reservation

DELETE /v1/api/reservations/{id}

Cancel/delete a reservation
curl -X DELETE http://localhost:8080/v1/api/reservations/42 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
@DeleteMapping("/{id}")
@SecurityRequirement(name = "JWT")
public ResponseEntity<Void> deleteUser(@PathVariable Integer id) {
    reservationService.deleteReservation(id);
    return ResponseEntity.noContent().build();
}

Reservation Entity Relationships

The reservation entity connects three key entities:
public class Reservation {
    private Integer id;
    private Date check_in;
    private Date check_out;
    private boolean valorated;
    
    // Foreign key relationships
    private User ID_cliente;      // Link to User (Client)
    private Housing housing;      // Link to Housing property
}
The DTO uses simplified fields (clientDni and housingCode) instead of full entity objects for easier JSON serialization.

User Flow Example

Complete Booking Journey

1

Browse properties

User searches for hotels in /room page
2

Select property

Clicks on “Ocean View Resort” to see details
3

Check authentication

System verifies user is logged in, redirects to login if needed
4

Enter dates

Fills form: Check-in (2026-06-01), Check-out (2026-06-05)
5

Submit booking

Clicks “Book Now” button
6

API call

Frontend sends POST request with JWT token
7

Server validation

Backend validates dates, user, and property existence
8

Create reservation

Database record created with auto-generated ID
9

Success feedback

User sees success message with booking confirmation
10

Post-booking

User can later write a review (sets valorated: true)

Retrieving User Information

The frontend retrieves the current user’s DNI for reservation creation:
getUserDni(): Observable<string | null> {
  const usernameemail = this.getUsername();
  
  return this.http.get<UserDTO[]>(`${environment.baseUrlApi}/users`).pipe(
    map(users => {
      const user = users.find(u => u.email === usernameemail);
      return user ? user.dni : null;
    }),
    catchError(err => {
      console.error('Error loading user data:', err);
      return of(null);
    })
  );
}
For better performance, consider caching user information after login instead of fetching the entire user list each time.

Best Practices

Always validate that check-out is after check-in:
const checkInDate = new Date(this.reservationForm.value.checkIn);
const checkOutDate = new Date(this.reservationForm.value.checkOut);

if (checkOutDate <= checkInDate) {
  // Show error message
}
Before creating a reservation, verify the property is available for the selected dates (implement on backend).
Display total price based on number of nights and property’s nightly rate:
const nights = Math.ceil(
  (checkOutDate - checkInDate) / (1000 * 60 * 60 * 24)
);
const totalPrice = nights * this.house.price;
Send confirmation email to user after successful reservation (implement in backend service).
Implement pessimistic locking or optimistic concurrency control to prevent double bookings.

Error Handling

Common Errors and Solutions

Cause: User not logged in or JWT token expiredSolution: Redirect to login page, then return to reservation after authentication
Cause: Invalid date format or missing required fieldsSolution: Validate form data before submission, show specific field errors
Cause: Housing property doesn’t exist or was deletedSolution: Verify property exists before showing booking form
Cause: User doesn’t have permission (e.g., trying to modify someone else’s reservation)Solution: Implement proper authorization checks on backend

Linking Reservations to Reviews

The valorated field creates a relationship between reservations and reviews:
// After check-out, users can write reviews
if (reservation.valorated === false && isPastCheckOut(reservation.checkOut)) {
  // Show "Write a Review" button
}

// When review is submitted, update reservation
onSubmitReview(): void {
  this.reviewService.createReview(reviewData).subscribe({
    next: () => {
      // Update the valorated flag
      this.reservationService.updateReservation(reservationId, {
        ...reservation,
        valorated: true
      }).subscribe();
    }
  });
}
This prevents users from reviewing the same reservation multiple times and helps track which stays have been reviewed.

Authentication

Learn how to log in before making reservations

Browsing Housing

Find the perfect property to book

Writing Reviews

Share your experience after your stay

User Roles

Understand user permissions for reservations

Build docs developers (and LLMs) love