diff --git a/SDG-Backend-Barracuda/Models/DeckModel.cs b/SDG-Backend-Barracuda/Models/DeckModel.cs new file mode 100644 index 0000000..1317477 --- /dev/null +++ b/SDG-Backend-Barracuda/Models/DeckModel.cs @@ -0,0 +1,148 @@ +using Dapper; +using Npgsql; + +namespace SDG_Backend_Barracuda.Models; + +public record Deck +{ + public int Id { get; init; } + public string Name { get; init; } = string.Empty; + public int CardListId { get; init; } + public IEnumerable? GameList { get; init; } + + public Deck() { } + + public Deck(int id, string name, int cardListId, IEnumerable? gameList = null) + { + Id = id; + Name = name; + CardListId = cardListId; + GameList = gameList; + } +} + +public record DeckInformation(string Name, int CardListId, IEnumerable? GameIds = null); + +public interface IDeckModel : IDatabaseModel +{ +} + +public class DeckModel(NpgsqlDataSource dataSource) : IDeckModel, IEndpointRouteHandler +{ + public static void MapEndpoints(IEndpointRouteBuilder router) + { + var deckEndpoint = router.MapGroup("/deck"); + + // Create + deckEndpoint.MapPost("/", async (DeckInformation input, IDeckModel model) => + { + var newDeck = await model.Create(input); + return Results.Created($"/deck/{newDeck.Id}", newDeck); + }); + + // Get all + deckEndpoint.MapGet("/", async (IDeckModel model) => + Results.Ok(await model.GetAll())); + + // Get one + deckEndpoint.MapGet("/{id}", async (int id, IDeckModel model) => + await model.GetById(id) is { } d ? Results.Ok(d) : Results.NotFound()); + + // Update + deckEndpoint.MapPut("/{id}", async (int id, DeckInformation input, IDeckModel model) => + await model.Update(id, input) is { } d ? Results.Ok(d) : Results.NotFound()); + + // Delete + deckEndpoint.MapDelete("/{id}", async (int id, IDeckModel model) => + await model.Delete(id) ? Results.NoContent() : Results.NotFound()); + } + + public async Task> GetAll() + { + await using var connection = await dataSource.OpenConnectionAsync(); + var sql = """SELECT * FROM "Deck";"""; + var decks = await connection.QueryAsync(sql); + + var result = new List(); + foreach (var deck in decks) + { + result.Add(await GetById(deck.Id) ?? deck); + } + return result; + } + + public async Task GetById(int id) + { + await using var connection = await dataSource.OpenConnectionAsync(); + var deckSql = """SELECT * FROM "Deck" WHERE "Id" = @Id;"""; + var deck = await connection.QueryFirstOrDefaultAsync(deckSql, new { Id = id }); + if (deck == null) return null; + + var gamesSql = """ + SELECT g.* + FROM "Game" g + JOIN "DeckGame" dg ON g."Id" = dg."GameId" + WHERE dg."DeckId" = @Id; + """; + var games = await connection.QueryAsync(gamesSql, new { Id = id }); + + return deck with { GameList = games }; + } + + public async Task Create(DeckInformation input) + { + await using var connection = await dataSource.OpenConnectionAsync(); + var sql = """ + INSERT INTO "Deck" ("Name", "CardListId") + VALUES (@Name, @CardListId) + RETURNING "Id", "Name", "CardListId"; + """; + var newDeck = await connection.QuerySingleAsync(sql, new { input.Name, input.CardListId }); + + if (input.GameIds != null) + { + foreach (var gameId in input.GameIds) + { + await connection.ExecuteAsync( + """INSERT INTO "DeckGame" ("DeckId", "GameId") VALUES (@DeckId, @GameId)""", + new { DeckId = newDeck.Id, GameId = gameId }); + } + } + + return (await GetById(newDeck.Id))!; + } + + public async Task Update(int id, DeckInformation input) + { + await using var connection = await dataSource.OpenConnectionAsync(); + + var sql = """ + UPDATE "Deck" + SET "Name" = @Name, "CardListId" = @CardListId + WHERE "Id" = @Id + RETURNING "Id", "Name", "CardListId"; + """; + var updatedDeck = await connection.QueryFirstOrDefaultAsync(sql, new { Id = id, input.Name, input.CardListId }); + if (updatedDeck == null) return null; + + await connection.ExecuteAsync("""DELETE FROM "DeckGame" WHERE "DeckId" = @Id""", new { Id = id }); + if (input.GameIds != null) + { + foreach (var gameId in input.GameIds) + { + await connection.ExecuteAsync( + """INSERT INTO "DeckGame" ("DeckId", "GameId") VALUES (@Id, @GameId)""", + new { Id = id, GameId = gameId }); + } + } + + return await GetById(id); + } + + public async Task Delete(int id) + { + await using var connection = await dataSource.OpenConnectionAsync(); + var rowsAffected = await connection.ExecuteAsync("""DELETE FROM "Deck" WHERE "Id" = @Id""", new { Id = id }); + return rowsAffected > 0; + } +}