Add game website URL to suggestions and results

This commit is contained in:
2026-01-28 20:25:02 +01:00
parent e15dd02228
commit 1b96d2af46
8 changed files with 228 additions and 4 deletions

View File

@@ -1,7 +1,7 @@
namespace GameList.Contracts;
public record SetNameRequest(string Name);
public record SuggestionRequest(string Name, string? Genre, string? Description, string? ScreenshotUrl, string? YoutubeUrl);
public record SuggestionDto(int Id, string Name, string? Genre, string? Description, string? ScreenshotUrl, string? YoutubeUrl);
public record SuggestionRequest(string Name, string? Genre, string? Description, string? ScreenshotUrl, string? YoutubeUrl, string? GameUrl);
public record SuggestionDto(int Id, string Name, string? Genre, string? Description, string? ScreenshotUrl, string? YoutubeUrl, string? GameUrl);
public record VoteRequest(int SuggestionId, int Score);
public record PhaseRequest(GameList.Domain.Phase Phase);

View File

@@ -38,6 +38,7 @@ public class AppDbContext : DbContext
builder.Property(s => s.Description).HasMaxLength(500);
builder.Property(s => s.ScreenshotUrl).HasMaxLength(2048);
builder.Property(s => s.YoutubeUrl).HasMaxLength(2048);
builder.Property(s => s.GameUrl).HasMaxLength(2048);
});
modelBuilder.Entity<Vote>(builder =>

View File

@@ -0,0 +1,182 @@
// <auto-generated />
using System;
using GameList.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace GameList.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20260128192420_AddGameUrlToSuggestion")]
partial class AddGameUrlToSuggestion
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.2");
modelBuilder.Entity("GameList.Domain.AppState", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CurrentPhase")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("AppState");
b.HasData(
new
{
Id = 1,
CurrentPhase = 0,
UpdatedAt = new DateTimeOffset(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0))
});
});
modelBuilder.Entity("GameList.Domain.Player", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("DisplayName")
.HasMaxLength(64)
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Players");
});
modelBuilder.Entity("GameList.Domain.Suggestion", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<string>("GameUrl")
.HasMaxLength(2048)
.HasColumnType("TEXT");
b.Property<string>("Genre")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<Guid>("PlayerId")
.HasColumnType("TEXT");
b.Property<string>("ScreenshotUrl")
.HasMaxLength(2048)
.HasColumnType("TEXT");
b.Property<string>("YoutubeUrl")
.HasMaxLength(2048)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("PlayerId");
b.ToTable("Suggestions");
});
modelBuilder.Entity("GameList.Domain.Vote", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<Guid>("PlayerId")
.HasColumnType("TEXT");
b.Property<int>("Score")
.HasColumnType("INTEGER");
b.Property<int>("SuggestionId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SuggestionId");
b.HasIndex("PlayerId", "SuggestionId")
.IsUnique();
b.ToTable("Votes");
});
modelBuilder.Entity("GameList.Domain.Suggestion", b =>
{
b.HasOne("GameList.Domain.Player", "Player")
.WithMany("Suggestions")
.HasForeignKey("PlayerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Player");
});
modelBuilder.Entity("GameList.Domain.Vote", b =>
{
b.HasOne("GameList.Domain.Player", "Player")
.WithMany("Votes")
.HasForeignKey("PlayerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GameList.Domain.Suggestion", "Suggestion")
.WithMany("Votes")
.HasForeignKey("SuggestionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Player");
b.Navigation("Suggestion");
});
modelBuilder.Entity("GameList.Domain.Player", b =>
{
b.Navigation("Suggestions");
b.Navigation("Votes");
});
modelBuilder.Entity("GameList.Domain.Suggestion", b =>
{
b.Navigation("Votes");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameList.Data.Migrations
{
/// <inheritdoc />
public partial class AddGameUrlToSuggestion : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "GameUrl",
table: "Suggestions",
type: "TEXT",
maxLength: 2048,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "GameUrl",
table: "Suggestions");
}
}
}

View File

@@ -73,6 +73,10 @@ namespace GameList.Data.Migrations
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<string>("GameUrl")
.HasMaxLength(2048)
.HasColumnType("TEXT");
b.Property<string>("Genre")
.HasMaxLength(50)
.HasColumnType("TEXT");

View File

@@ -26,6 +26,9 @@ public class Suggestion
[MaxLength(2048)]
public string? YoutubeUrl { get; set; }
[MaxLength(2048)]
public string? GameUrl { get; set; }
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
public ICollection<Vote> Votes { get; set; } = new List<Vote>();

View File

@@ -27,6 +27,7 @@ public static class ResultsEndpoints
Average = s.Votes.Count == 0 ? 0 : s.Votes.Average(v => v.Score),
s.ScreenshotUrl,
s.YoutubeUrl,
s.GameUrl,
s.Description,
s.Genre
})

View File

@@ -27,13 +27,14 @@ public static class SuggestEndpoints
s.Description,
s.ScreenshotUrl,
s.YoutubeUrl,
s.GameUrl,
s.CreatedAt
})
.ToListAsync();
var ordered = mine
.OrderBy(s => s.CreatedAt)
.Select(s => new SuggestionDto(s.Id, s.Name, s.Genre, s.Description, s.ScreenshotUrl, s.YoutubeUrl));
.Select(s => new SuggestionDto(s.Id, s.Name, s.Genre, s.Description, s.ScreenshotUrl, s.YoutubeUrl, s.GameUrl));
return Results.Ok(ordered);
});
@@ -69,7 +70,8 @@ public static class SuggestEndpoints
Genre = EndpointHelpers.TrimTo(request.Genre, 50),
Description = EndpointHelpers.TrimTo(request.Description, 500),
ScreenshotUrl = EndpointHelpers.TrimTo(request.ScreenshotUrl, 2048),
YoutubeUrl = EndpointHelpers.TrimTo(request.YoutubeUrl, 2048)
YoutubeUrl = EndpointHelpers.TrimTo(request.YoutubeUrl, 2048),
GameUrl = EndpointHelpers.TrimTo(request.GameUrl, 2048)
};
db.Suggestions.Add(suggestion);
@@ -110,6 +112,7 @@ public static class SuggestEndpoints
s.Description,
s.ScreenshotUrl,
s.YoutubeUrl,
s.GameUrl,
Author = s.Player!.DisplayName,
s.CreatedAt
})
@@ -125,6 +128,7 @@ public static class SuggestEndpoints
s.Description,
s.ScreenshotUrl,
s.YoutubeUrl,
s.GameUrl,
s.Author
});