Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/Contracts/CheckInRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Contracts
{
public record CheckInRequest(string GuestEmail);
}
12 changes: 12 additions & 0 deletions api/Contracts/ErrorResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization;

namespace Contracts
{
public record ErrorResponse(
string Title,
string Detail,
[property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? ResourceType = null,
[property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? ResourceId = null,
[property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] Dictionary<string, string[]>? Errors = null
);
}
11 changes: 11 additions & 0 deletions api/Contracts/ImportResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Contracts
{
public record ImportResult(
int TotalRows,
int Imported,
int Failed,
List<ImportError> Errors
);

public record ImportError(int Line, string RoomNumber, string Message);
}
10 changes: 10 additions & 0 deletions api/Contracts/ReservationRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Contracts
{
public class ReservationRequest
{
public required string RoomNumber { get; set; }
public required string GuestEmail { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
}
6 changes: 6 additions & 0 deletions api/Contracts/UpdateRoomStateRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Models;

namespace Contracts
{
public record UpdateRoomStateRequest(State State);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@

namespace Controllers
{
[Tags("Guests"), Route("guest")]
public class GuestController : Controller
[ApiController]
[Tags("Guests"), Route("guests")]
public class GuestsController : ControllerBase
{
private GuestRepository _repo;

public GuestController(GuestRepository guestRepository)
public GuestsController(GuestRepository guestRepository)
{
_repo = guestRepository;
}

[HttpGet, Produces("application/json"), Route("")]
[ProducesResponseType(typeof(IEnumerable<Guest>), StatusCodes.Status200OK)]
public async Task<ActionResult<Guest>> GetGuests()
{
var guests = await _repo.GetGuests();

return Json(guests);
return Ok(guests);
}
}
}
78 changes: 0 additions & 78 deletions api/Controllers/ReservationController.cs

This file was deleted.

98 changes: 98 additions & 0 deletions api/Controllers/ReservationsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Contracts;
using FluentValidation;
using Models;
using Repositories;

namespace Controllers
{
[ApiController]
[Tags("Reservations"), Route("reservations")]
public class ReservationsController : ControllerBase
{
private ReservationRepository _repo { get; set; }
private IValidator<ReservationRequest> _validator { get; set; }

public ReservationsController(ReservationRepository reservationRepository, IValidator<ReservationRequest> validator)
{
_repo = reservationRepository;
_validator = validator;
}

[Authorize]
[HttpGet, Produces("application/json"), Route("")]
[ProducesResponseType(typeof(IEnumerable<Reservation>), StatusCodes.Status200OK)]
public async Task<ActionResult<IEnumerable<Reservation>>> GetReservations(
[FromQuery] DateTime? from,
[FromQuery] DateTime? to,
[FromQuery] string? roomNumber,
[FromQuery] string? guestEmail)
{
var reservations = await _repo.GetReservations(from, to, roomNumber, guestEmail);

return Ok(reservations);
}

[HttpGet, Produces("application/json"), Route("{reservationId}")]
[ProducesResponseType(typeof(Reservation), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public async Task<ActionResult<Reservation>> GetReservation(Guid reservationId)
{
var reservation = await _repo.GetReservation(reservationId);

return Ok(reservation);
}

/// <summary>
/// Create a new reservation, to generate the GUID ID on the server, send an Empty GUID (all 0s)
/// </summary>
/// <param name="request"> The request/booking data. </param>
/// <returns> The created reservation. </returns>
[HttpPost, Produces("application/json"), Route("")]
[ProducesResponseType(typeof(Reservation), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Reservation>> BookReservation([FromBody] ReservationRequest request)
{
await _validator.ValidateAndThrowAsync(request);

var createdReservation = await _repo.CreateReservation(request);
return Created($"/reservations/{createdReservation.Id}", createdReservation);
}

[Authorize]
[HttpPost, Produces("application/json"), Route("{reservationId}/check-in")]
[ProducesResponseType(typeof(Reservation), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
public async Task<ActionResult<Reservation>> CheckIn(Guid reservationId, [FromBody] CheckInRequest request)
{
var reservation = await _repo.CheckIn(reservationId, request.GuestEmail);
return Ok(reservation);
}

[Authorize]
[HttpPost, Produces("application/json"), Route("{reservationId}/check-out")]
[ProducesResponseType(typeof(Reservation), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
public async Task<ActionResult<Reservation>> CheckOut(Guid reservationId, [FromBody] CheckInRequest request)
{
var reservation = await _repo.CheckOut(reservationId, request.GuestEmail);
return Ok(reservation);
}

[Authorize]
[HttpDelete, Produces("application/json"), Route("{reservationId}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public async Task<IActionResult> DeleteReservation(Guid reservationId)
{
await _repo.DeleteReservation(reservationId);

return NoContent();
}
}
}
77 changes: 0 additions & 77 deletions api/Controllers/RoomController.cs

This file was deleted.

Loading