diff --git a/Portfolio.Application/Services/PokemonService/IPokemonService.cs b/Portfolio.Application/Services/PokemonService/IPokemonService.cs index 9d0164f..4be39b9 100644 --- a/Portfolio.Application/Services/PokemonService/IPokemonService.cs +++ b/Portfolio.Application/Services/PokemonService/IPokemonService.cs @@ -13,5 +13,6 @@ namespace Portfolio.Application.Services.PokemonService Task GetPokemonByIdAsync(int id); Task AddPokemonAsync(Pokemon pokemon); Task DeletePokemonAsync(int pokemonId); + Task UpdatePokemonAsync(Pokemon pokemon); } } diff --git a/Portfolio.Application/Services/PokemonService/PokemonService.cs b/Portfolio.Application/Services/PokemonService/PokemonService.cs index fb4f7dd..72f34ff 100644 --- a/Portfolio.Application/Services/PokemonService/PokemonService.cs +++ b/Portfolio.Application/Services/PokemonService/PokemonService.cs @@ -37,5 +37,10 @@ namespace Portfolio.Application.Services.PokemonService { return await _pokemonRepository.GetPokemonByIdAsync(id); } + + public async Task UpdatePokemonAsync(Pokemon pokemon) + { + await _pokemonRepository.UpdatePokemonAsync(pokemon); + } } } diff --git a/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs b/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs index 87a7dca..3fb4fb6 100644 --- a/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs +++ b/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs @@ -12,6 +12,7 @@ namespace Portfolio.Domain.Features.Pokemon Task GetPokemonByIdAsync(int id); Task AddPokemonAsync(Pokemon pokemon); Task DeletePokemonAsync(int pokemonId); + Task UpdatePokemonAsync(Pokemon pokemon); } } diff --git a/Portfolio.Domain/Features/Pokemon/Pokemon.cs b/Portfolio.Domain/Features/Pokemon/Pokemon.cs index fc6c7e4..a92debf 100644 --- a/Portfolio.Domain/Features/Pokemon/Pokemon.cs +++ b/Portfolio.Domain/Features/Pokemon/Pokemon.cs @@ -15,6 +15,8 @@ namespace Portfolio.Domain.Features.Pokemon public string? VariationName { get; set; } public required string SleepType { get; set; } public required string Speciality { get; set; } + public string? PokemonImageUrl { get; set; } + public string? PokemonShinyImageUrl { get; set; } } diff --git a/Portfolio.Infrastructure/Migrations/20250321161454_AddPokemonImageUrl.Designer.cs b/Portfolio.Infrastructure/Migrations/20250321161454_AddPokemonImageUrl.Designer.cs new file mode 100644 index 0000000..1e6748b --- /dev/null +++ b/Portfolio.Infrastructure/Migrations/20250321161454_AddPokemonImageUrl.Designer.cs @@ -0,0 +1,118 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Portfolio.Infrastructure; + +#nullable disable + +namespace Portfolio.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250321161454_AddPokemonImageUrl")] + partial class AddPokemonImageUrl + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon.Pokemon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("IsVariation") + .HasColumnType("bit"); + + b.Property("PokemonId") + .HasColumnType("int"); + + b.Property("PokemonImageUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("PokemonName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SleepType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Speciality") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("VariationName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Pokemons"); + }); + + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BerryRating") + .HasColumnType("int"); + + b.Property("IngredientRating") + .HasColumnType("int"); + + b.Property("Nature") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SkillRating") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PokemonNatures"); + }); + + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BerryRank") + .HasColumnType("int"); + + b.Property("IngredientRank") + .HasColumnType("int"); + + b.Property("SkillRank") + .HasColumnType("int"); + + b.Property("SubSkill") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PokemonSubskills"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Portfolio.Infrastructure/Migrations/20250321161454_AddPokemonImageUrl.cs b/Portfolio.Infrastructure/Migrations/20250321161454_AddPokemonImageUrl.cs new file mode 100644 index 0000000..5401a5d --- /dev/null +++ b/Portfolio.Infrastructure/Migrations/20250321161454_AddPokemonImageUrl.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Portfolio.Infrastructure.Migrations +{ + /// + public partial class AddPokemonImageUrl : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PokemonImageUrl", + table: "Pokemons", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PokemonImageUrl", + table: "Pokemons"); + } + } +} diff --git a/Portfolio.Infrastructure/Migrations/20250321165440_AddPokemonShinyImageUrl.Designer.cs b/Portfolio.Infrastructure/Migrations/20250321165440_AddPokemonShinyImageUrl.Designer.cs new file mode 100644 index 0000000..ad18175 --- /dev/null +++ b/Portfolio.Infrastructure/Migrations/20250321165440_AddPokemonShinyImageUrl.Designer.cs @@ -0,0 +1,121 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Portfolio.Infrastructure; + +#nullable disable + +namespace Portfolio.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250321165440_AddPokemonShinyImageUrl")] + partial class AddPokemonShinyImageUrl + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon.Pokemon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("IsVariation") + .HasColumnType("bit"); + + b.Property("PokemonId") + .HasColumnType("int"); + + b.Property("PokemonImageUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("PokemonName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PokemonShinyImageUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("SleepType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Speciality") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("VariationName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Pokemons"); + }); + + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BerryRating") + .HasColumnType("int"); + + b.Property("IngredientRating") + .HasColumnType("int"); + + b.Property("Nature") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SkillRating") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PokemonNatures"); + }); + + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BerryRank") + .HasColumnType("int"); + + b.Property("IngredientRank") + .HasColumnType("int"); + + b.Property("SkillRank") + .HasColumnType("int"); + + b.Property("SubSkill") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PokemonSubskills"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Portfolio.Infrastructure/Migrations/20250321165440_AddPokemonShinyImageUrl.cs b/Portfolio.Infrastructure/Migrations/20250321165440_AddPokemonShinyImageUrl.cs new file mode 100644 index 0000000..b9cdd02 --- /dev/null +++ b/Portfolio.Infrastructure/Migrations/20250321165440_AddPokemonShinyImageUrl.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Portfolio.Infrastructure.Migrations +{ + /// + public partial class AddPokemonShinyImageUrl : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PokemonShinyImageUrl", + table: "Pokemons", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PokemonShinyImageUrl", + table: "Pokemons"); + } + } +} diff --git a/Portfolio.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/Portfolio.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 93ef60a..be99988 100644 --- a/Portfolio.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Portfolio.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -35,10 +35,16 @@ namespace Portfolio.Infrastructure.Migrations b.Property("PokemonId") .HasColumnType("int"); + b.Property("PokemonImageUrl") + .HasColumnType("nvarchar(max)"); + b.Property("PokemonName") .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("PokemonShinyImageUrl") + .HasColumnType("nvarchar(max)"); + b.Property("SleepType") .IsRequired() .HasColumnType("nvarchar(max)"); @@ -55,7 +61,7 @@ namespace Portfolio.Infrastructure.Migrations b.ToTable("Pokemons"); }); - modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNatures", b => + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -81,7 +87,7 @@ namespace Portfolio.Infrastructure.Migrations b.ToTable("PokemonNatures"); }); - modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskills", b => + modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/Portfolio.Infrastructure/Repositories/PokemonRepository.cs b/Portfolio.Infrastructure/Repositories/PokemonRepository.cs index 85c1a3e..bb3649d 100644 --- a/Portfolio.Infrastructure/Repositories/PokemonRepository.cs +++ b/Portfolio.Infrastructure/Repositories/PokemonRepository.cs @@ -41,5 +41,10 @@ namespace Portfolio.Infrastructure.Repositories } } + public async Task UpdatePokemonAsync(Pokemon pokemon) + { + _context.Pokemons.Update(pokemon); + await _context.SaveChangesAsync(); + } } } diff --git a/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor b/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor index ee7bdd1..f49e1ab 100644 --- a/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor +++ b/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor @@ -1,5 +1,6 @@ @inject IPokemonService PokemonService @inject IJSRuntime JS +@inject NavigationManager Navigation @attribute [StreamRendering] @rendermode InteractiveServer @@ -18,8 +19,9 @@ else
-
+

Available Pokémon

+

@(pokemons.Count()) Pokemon

@@ -46,23 +48,30 @@ else { - + @{ - string baseUrl = pokemon.IsVariation - ? $"/pokemon_images/normal/{pokemon.PokemonId}-{pokemon.VariationName.ToLower()}{pokemon.PokemonName.ToLower()}.png" - : $"/pokemon_images/normal/{pokemon.PokemonId}.png"; - - string shinyUrl = pokemon.IsVariation - ? $"/pokemon_images/shiny/{pokemon.PokemonId}-{pokemon.VariationName.ToLower()}{pokemon.PokemonName.ToLower()}.png" - : $"/pokemon_images/shiny/{pokemon.PokemonId}.png"; + string baseUrl = pokemon.PokemonImageUrl; + string shinyUrl = pokemon.PokemonShinyImageUrl; } -
-
- - + @if(shinyUrl == null){ +
+
+ +
-
+ + } + else + { +
+
+ + +
+
+ + } @@ -95,8 +104,13 @@ else

@pokemon.Speciality

- + +
+ + +
+ + +
+
+ + +
diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor b/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor new file mode 100644 index 0000000..f59a242 --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor @@ -0,0 +1,92 @@ +@page "/pokemonsleep/edit/{id:int}" +@inject IPokemonService PokemonService +@inject NavigationManager Navigation + +@attribute [StreamRendering] +@rendermode InteractiveServer + +Edit Pokémon + + +@if (pokemon == null) +{ +

Loading...

+} +else +{ +
+
+
+
+

Edit Pokémon

+
+
+
+ +
+ + + +
+
+ # + + +
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ + +
+ + +
+
+ + +
+ + + +
+
+
+} + +@code { + [Parameter] public int Id { get; set; } + private Pokemon? pokemon; + + protected override async Task OnInitializedAsync() + { + pokemon = await PokemonService.GetPokemonByIdAsync(Id); + } + + private async Task HandleSubmit() + { + await PokemonService.UpdatePokemonAsync(pokemon); + Navigation.NavigateTo("/pokemonsleep"); + } + + private void Cancel() + { + Navigation.NavigateTo("/pokemonsleep"); + } +} \ No newline at end of file