diff --git a/Portfolio.Application/Services/PokemonService/IPokemonService.cs b/Portfolio.Application/Services/PokemonService/IPokemonService.cs index 4be39b9..fc41f5a 100644 --- a/Portfolio.Application/Services/PokemonService/IPokemonService.cs +++ b/Portfolio.Application/Services/PokemonService/IPokemonService.cs @@ -10,7 +10,12 @@ namespace Portfolio.Application.Services.PokemonService public interface IPokemonService { Task> GetAllPokemonAsync(); + Task GetPokemonByPokemonIdAsync(int id); Task GetPokemonByIdAsync(int id); + Task> GetAllPokemonIdsAsync(); + Task GetPreviousPokemonIdAsync(int id); + Task GetNextPokemonIdAsync(int id); + Task GetVariationPokemonIdAsync(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 72f34ff..024230f 100644 --- a/Portfolio.Application/Services/PokemonService/PokemonService.cs +++ b/Portfolio.Application/Services/PokemonService/PokemonService.cs @@ -33,14 +33,40 @@ namespace Portfolio.Application.Services.PokemonService } + public async Task> GetAllPokemonIdsAsync() + { + return await _pokemonRepository.GetAllPokemonIdsAsync(); + } + + public async Task GetNextPokemonIdAsync(int id) + { + return await _pokemonRepository.GetNextPokemonIdAsync(id); + } + + public async Task GetPokemonByPokemonIdAsync(int id) + { + return await _pokemonRepository.GetPokemonByPokemonIdAsync(id); + } + public async Task GetPokemonByIdAsync(int id) { return await _pokemonRepository.GetPokemonByIdAsync(id); } + public async Task GetPreviousPokemonIdAsync(int id) + { + return await _pokemonRepository.GetPreviousPokemonIdAsync(id); + + } + public async Task UpdatePokemonAsync(Pokemon pokemon) { await _pokemonRepository.UpdatePokemonAsync(pokemon); } + + public async Task GetVariationPokemonIdAsync(int id) + { + return await _pokemonRepository.GetVariationPokemonIdAsync(id); + } } } diff --git a/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs b/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs index 3fb4fb6..277f39f 100644 --- a/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs +++ b/Portfolio.Domain/Features/Pokemon/IPokemonRepository.cs @@ -10,6 +10,11 @@ namespace Portfolio.Domain.Features.Pokemon { Task> GetAllPokemonsAsync(); Task GetPokemonByIdAsync(int id); + Task GetPokemonByPokemonIdAsync(int id); + Task> GetAllPokemonIdsAsync(); + Task GetPreviousPokemonIdAsync(int currentPokemonId); + Task GetNextPokemonIdAsync(int currentPokemonId); + Task GetVariationPokemonIdAsync(int pokemonId); Task AddPokemonAsync(Pokemon pokemon); Task DeletePokemonAsync(int pokemonId); Task UpdatePokemonAsync(Pokemon pokemon); diff --git a/Portfolio.Infrastructure/Repositories/PokemonRepository.cs b/Portfolio.Infrastructure/Repositories/PokemonRepository.cs index bb3649d..22ed845 100644 --- a/Portfolio.Infrastructure/Repositories/PokemonRepository.cs +++ b/Portfolio.Infrastructure/Repositories/PokemonRepository.cs @@ -21,11 +21,14 @@ namespace Portfolio.Infrastructure.Repositories { return await _context.Pokemons.ToListAsync(); } + public async Task GetPokemonByPokemonIdAsync(int id) + { + return await _context.Pokemons.FirstOrDefaultAsync(p => p.PokemonId == id); + } public async Task GetPokemonByIdAsync(int id) { return await _context.Pokemons.FirstOrDefaultAsync(p => p.Id == id); } - public async Task AddPokemonAsync(Pokemon pokemon) { _context.Pokemons.Add(pokemon); @@ -46,5 +49,68 @@ namespace Portfolio.Infrastructure.Repositories _context.Pokemons.Update(pokemon); await _context.SaveChangesAsync(); } + + public async Task GetPreviousPokemonIdAsync(int currentPokemonId) + { + // Get the previous Pokémon's PokemonId + var prevPokemonId = await _context.Pokemons + .Where(p => p.PokemonId < currentPokemonId) + .OrderByDescending(p => p.PokemonId) + .Select(p => (int?)p.PokemonId) + .FirstOrDefaultAsync(); + + // If no previous PokemonId is found, wrap around to the last one + if (prevPokemonId == null) + { + prevPokemonId = await _context.Pokemons + .OrderByDescending(p => p.PokemonId) // Get the last PokemonId + .Select(p => (int?)p.PokemonId) + .FirstOrDefaultAsync(); + } + + return prevPokemonId; + } + + public async Task GetNextPokemonIdAsync(int currentPokemonId) + { + // Get the next Pokémon's PokemonId + var nextPokemonId = await _context.Pokemons + .Where(p => p.PokemonId > currentPokemonId) + .OrderBy(p => p.PokemonId) + .Select(p => (int?)p.PokemonId) + .FirstOrDefaultAsync(); + + // If no next PokemonId is found, wrap around to the first one + if (nextPokemonId == null) + { + nextPokemonId = await _context.Pokemons + .OrderBy(p => p.PokemonId) // Get the first PokemonId + .Select(p => (int?)p.PokemonId) + .FirstOrDefaultAsync(); + } + + return nextPokemonId; + } + + public async Task> GetAllPokemonIdsAsync() + { + return await _context.Pokemons + .OrderBy(p => p.PokemonId) // Ensure it's ordered by PokemonId + .Select(p => p.PokemonId) + .ToListAsync(); + } + + public async Task GetVariationPokemonIdAsync(int pokemonId) + { + // Find a variation for the given PokemonId (where IsVariation is true) + var variation = await _context.Pokemons + .Where(p => p.PokemonId == pokemonId && p.IsVariation) + .FirstOrDefaultAsync(); + + // Return the Id of the variation, or null if no variation is found + return variation?.Id; + } + + } } diff --git a/Portfolio.WebUI.Server/Components/Component/Loading.razor b/Portfolio.WebUI.Server/Components/Component/Loading.razor new file mode 100644 index 0000000..7e8f1c3 --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Component/Loading.razor @@ -0,0 +1,9 @@ +
+
G
+
N
+
I
+
D
+
A
+
O
+
L
+
\ No newline at end of file diff --git a/Portfolio.WebUI.Server/Components/Component/Loading.razor.css b/Portfolio.WebUI.Server/Components/Component/Loading.razor.css new file mode 100644 index 0000000..f64eb57 --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Component/Loading.razor.css @@ -0,0 +1,195 @@ +body { + background: #000; +} + +#load { + position: absolute; + width: 600px; + height: 36px; + left: 50%; + top: 40%; + margin-left: -300px; + overflow: visible; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: default; +} + + #load div { + position: absolute; + width: 20px; + height: 36px; + opacity: 0; + font-family: Helvetica, Arial, sans-serif; + animation: move 3s linear infinite; + -o-animation: move 3s linear infinite; + -moz-animation: move 3s linear infinite; + -webkit-animation: move 3s linear infinite; + transform: rotate(180deg); + -o-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -webkit-transform: rotate(180deg); + color: #35C4F0; + } + + #load div:nth-child(2) { + animation-delay: 0.2s; + -o-animation-delay: 0.2s; + -moz-animation-delay: 0.2s; + -webkit-animation-delay: 0.2s; + } + + #load div:nth-child(3) { + animation-delay: 0.4s; + -o-animation-delay: 0.4s; + -webkit-animation-delay: 0.4s; + -webkit-animation-delay: 0.4s; + } + + #load div:nth-child(4) { + animation-delay: 0.6s; + -o-animation-delay: 0.6s; + -moz-animation-delay: 0.6s; + -webkit-animation-delay: 0.6s; + } + + #load div:nth-child(5) { + animation-delay: 0.8s; + -o-animation-delay: 0.8s; + -moz-animation-delay: 0.8s; + -webkit-animation-delay: 0.8s; + } + + #load div:nth-child(6) { + animation-delay: 1s; + -o-animation-delay: 1s; + -moz-animation-delay: 1s; + -webkit-animation-delay: 1s; + } + + #load div:nth-child(7) { + animation-delay: 1.2s; + -o-animation-delay: 1.2s; + -moz-animation-delay: 1.2s; + -webkit-animation-delay: 1.2s; + } + +@keyframes move { + 0% { + left: 0; + opacity: 0; + } + + 35% { + left: 41%; + -moz-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 65% { + left: 59%; + -moz-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 100% { + left: 100%; + -moz-transform: rotate(-180deg); + -webkit-transform: rotate(-180deg); + -o-transform: rotate(-180deg); + transform: rotate(-180deg); + opacity: 0; + } +} + +@-moz-keyframes move { + 0% { + left: 0; + opacity: 0; + } + + 35% { + left: 41%; + -moz-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 65% { + left: 59%; + -moz-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 100% { + left: 100%; + -moz-transform: rotate(-180deg); + transform: rotate(-180deg); + opacity: 0; + } +} + +@-webkit-keyframes move { + 0% { + left: 0; + opacity: 0; + } + + 35% { + left: 41%; + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 65% { + left: 59%; + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 100% { + left: 100%; + -webkit-transform: rotate(-180deg); + transform: rotate(-180deg); + opacity: 0; + } +} + +@-o-keyframes move { + 0% { + left: 0; + opacity: 0; + } + + 35% { + left: 41%; + -o-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 65% { + left: 59%; + -o-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + 100% { + left: 100%; + -o-transform: rotate(-180deg); + transform: rotate(-180deg); + opacity: 0; + } +} diff --git a/Portfolio.WebUI.Server/Components/Component/PokemonCard.razor b/Portfolio.WebUI.Server/Components/Component/PokemonCard.razor index 17bc90f..46a1c84 100644 --- a/Portfolio.WebUI.Server/Components/Component/PokemonCard.razor +++ b/Portfolio.WebUI.Server/Components/Component/PokemonCard.razor @@ -28,7 +28,7 @@ -
+
@if (string.IsNullOrEmpty(_pokemon.FlavorText)) {

[ Pokemon Flavor Text Placeholder ]

diff --git a/Portfolio.WebUI.Server/Components/Component/PokemonEditButton.razor b/Portfolio.WebUI.Server/Components/Component/PokemonEditButton.razor new file mode 100644 index 0000000..f02aa0f --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Component/PokemonEditButton.razor @@ -0,0 +1,6 @@ +@inject NavigationManager Navigation + \ No newline at end of file diff --git a/Portfolio.WebUI.Server/Components/Component/PokemonEditButton.razor.cs b/Portfolio.WebUI.Server/Components/Component/PokemonEditButton.razor.cs new file mode 100644 index 0000000..4f8b34b --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Component/PokemonEditButton.razor.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + +namespace Portfolio.WebUI.Server.Components.Component +{ + public partial class PokemonEditButton + { + [Parameter] public int PokemonId { get; set; } + + private void EditPokemon(int PokemonId) + { + Navigation.NavigateTo($"/pokemonsleep/edit/{PokemonId}"); + } + } +} diff --git a/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor b/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor index d6b3b13..e6098fa 100644 --- a/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor +++ b/Portfolio.WebUI.Server/Components/Component/PokemonTable.razor @@ -6,62 +6,63 @@ @rendermode InteractiveServer - -@if (pokemons == null) -{ -

Loading...

-} -else -{ - -
+ +
- -
-
-
-

Available Pokémon

-

@(pokemons.Count()) Pokemon

-
+ +
+
+
+

Available Pokémon

+

@(pokemons.Count()) Pokemon

+
- -
- - - - - - - - - - - - - - + +
+
#PokemonTypeSleep TypeSpeciality
+ + + + + + + + + + + + + @if(pokemons == null) + { + + + + } + else + { @foreach (var pokemon in pokemons) { - + @{ string baseUrl = pokemon.PokemonImageUrl; string shinyUrl = pokemon.PokemonShinyImageUrl; } @@ -83,22 +84,22 @@ else { @if (pokemon.VariationName == "Alolan") { - + } @if (pokemon.VariationName == "Paldean") { - + } } else // Otherwise, Base Case { - + } - @@ -115,14 +116,10 @@ else } + } + -
#PokemonTypeSleep TypeSpeciality
- @if(shinyUrl == null){ + @if (shinyUrl == null) + {
- + } else { @@ -71,7 +72,7 @@ else - + }
Alolan @pokemon.PokemonName Alolan @pokemon.PokemonName Paldean @pokemon.PokemonName Paldean @pokemon.PokemonName @pokemon.PokemonName @pokemon.PokemonName -
+
+
- +
-
+
+
+ -} diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonCreate.razor b/Portfolio.WebUI.Server/Components/Pages/PokemonCreate.razor index 0d6ea81..c1af132 100644 --- a/Portfolio.WebUI.Server/Components/Pages/PokemonCreate.razor +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonCreate.razor @@ -33,7 +33,7 @@ else -
+
# @@ -43,6 +43,53 @@ else
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+
+
@@ -59,31 +106,6 @@ else
- - - -
- - - - - - - -
- - -
- - - - - - - - -
-
@@ -93,8 +115,12 @@ else
- - + + +
+ + +
diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor b/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor index ee8123c..7c91440 100644 --- a/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor @@ -1,6 +1,7 @@ @page "/pokemonsleep/edit/{id:int}" @inject IPokemonService PokemonService @inject NavigationManager Navigation +@inject IJSRuntime JSRuntime @attribute [StreamRendering] @rendermode InteractiveServer @@ -31,7 +32,8 @@ else -
+ +
# @@ -39,7 +41,9 @@ else
+
+
@@ -64,7 +68,7 @@ else
- +
@@ -73,7 +77,7 @@ else
- +
@@ -83,30 +87,46 @@ else
+ +
+
+ +
+ + Variation? +
+ + +
+ +
+
+
- +
+
- +
- - + +
+ + +
} - -@code { - -} \ No newline at end of file diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor.cs b/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor.cs index e2c71aa..f45d4e0 100644 --- a/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor.cs +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonEdit.razor.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; using Portfolio.Domain.Features.Pokemon; namespace Portfolio.WebUI.Server.Components.Pages @@ -16,12 +17,21 @@ namespace Portfolio.WebUI.Server.Components.Pages private async Task HandleSubmit() { await PokemonService.UpdatePokemonAsync(pokemon); - Navigation.NavigateTo("/pokemonsleep"); + //Navigation.NavigateTo("/pokemonsleep"); + await JSRuntime.InvokeVoidAsync("history.back"); } - private void Cancel() + private async void Cancel() { - Navigation.NavigateTo("/pokemonsleep"); + await JSRuntime.InvokeVoidAsync("history.back"); + } + + private bool HideLabel { get; set; } = true; + private void Toggle() + { + HideLabel = !HideLabel; + } + } } diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonSleep.razor b/Portfolio.WebUI.Server/Components/Pages/PokemonSleep.razor index 33f537c..5ffde90 100644 --- a/Portfolio.WebUI.Server/Components/Pages/PokemonSleep.razor +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonSleep.razor @@ -9,7 +9,7 @@ Pokémon Sleep
- + diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor b/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor index bc52d30..09e24ad 100644 --- a/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor @@ -1,5 +1,81 @@ @page "/pokemonsleep/pokemon/{id:int}" +@inject IPokemonService PokemonService +@inject NavigationManager Navigation -@code { +@attribute [StreamRendering] +@rendermode InteractiveServer + + + +@if (_pokemon == null) +{ +

Loading...

+} +else +{ + @_pokemon.PokemonName + + +
+
+ +
+ @if (_variationPokemonId != null) + { + @if (_variationPokemonId != null && _pokemonVariant == null){ +

Loading...

+ } + else + { + @if(_pokemon.Id != _pokemonVariant.Id) + { +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ + } + else + { +
+ +
+ +
+
+ + } + } + } + else{ +
+ +
+ +
+
+ } +
+ +
+
} diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor.cs b/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor.cs new file mode 100644 index 0000000..10341e0 --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Components; +using Portfolio.Domain.Features.Pokemon; + +namespace Portfolio.WebUI.Server.Components.Pages +{ + public partial class PokemonView + { + [Parameter] public int Id { get; set; } + private Pokemon? _pokemon; + private Pokemon? _pokemonVariant; + private List _pokemonIds; + private int? _nextPokemonId; + private int? _previousPokemonId; + private int? _variationPokemonId; + private int _currentIndex; + + + protected override async Task OnParametersSetAsync() + { + _pokemon = await PokemonService.GetPokemonByPokemonIdAsync(Id); + + // These can be smart queries if your data is sorted by ID or by another property + _pokemonIds = await PokemonService.GetAllPokemonIdsAsync(); + _currentIndex = _pokemonIds.IndexOf(_pokemon.PokemonId); + //Console.WriteLine(_currentIndex); + + _nextPokemonId = await PokemonService.GetNextPokemonIdAsync(Id); + _previousPokemonId = await PokemonService.GetPreviousPokemonIdAsync(Id); + + _variationPokemonId = await PokemonService.GetVariationPokemonIdAsync(Id); + if (_variationPokemonId != null) + { + Console.WriteLine(_variationPokemonId); + _pokemonVariant = await PokemonService.GetPokemonByIdAsync((int)_variationPokemonId); + Console.WriteLine(_pokemonVariant.VariationName); + } + } + + private void NavigateToNext() + { + if (_nextPokemonId.HasValue) + Navigation.NavigateTo($"/pokemonsleep/pokemon/{_nextPokemonId.Value}"); + } + + private void NavigateToPrevious() + { + if (_previousPokemonId.HasValue) + Navigation.NavigateTo($"/pokemonsleep/pokemon/{_previousPokemonId.Value}"); + } + + } +} diff --git a/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor.css b/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor.css new file mode 100644 index 0000000..46800d1 --- /dev/null +++ b/Portfolio.WebUI.Server/Components/Pages/PokemonView.razor.css @@ -0,0 +1,2 @@ +body { +}